0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-30 22:34:13 -05:00

Fix data races in tests, closes #255

Signed-off-by: Alexei Dodon <adodon@cisco.com>
This commit is contained in:
Alexei Dodon 2021-11-10 14:31:03 +00:00 committed by Ramkumar Chinchani
parent 4d50ad2bb1
commit e900b09cfb
19 changed files with 589 additions and 975 deletions

View file

@ -22,27 +22,23 @@ import (
"testing" "testing"
"time" "time"
"golang.org/x/crypto/bcrypt"
"github.com/anuvu/zot/errors" "github.com/anuvu/zot/errors"
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
"github.com/anuvu/zot/pkg/storage" "github.com/anuvu/zot/pkg/storage"
. "github.com/anuvu/zot/test"
"github.com/chartmuseum/auth" "github.com/chartmuseum/auth"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
vldap "github.com/nmcclain/ldap"
godigest "github.com/opencontainers/go-digest" godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/phayes/freeport"
"github.com/stretchr/testify/assert"
vldap "github.com/nmcclain/ldap"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"golang.org/x/crypto/bcrypt"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
const ( const (
BaseURL = "http://127.0.0.1:%s"
BaseSecureURL = "https://127.0.0.1:%s"
username = "test" username = "test"
passphrase = "test" passphrase = "test"
ServerCert = "../../test/data/server.cert" ServerCert = "../../test/data/server.cert"
@ -66,53 +62,6 @@ type (
} }
) )
func getFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func getBaseURL(port string, secure bool) string {
if secure {
return fmt.Sprintf(BaseSecureURL, port)
}
return fmt.Sprintf(BaseURL, port)
}
func makeHtpasswdFile() string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n")
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func makeHtpasswdFileFromString(fileContent string) string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte(fileContent)
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func getCredString(username, password string) string { func getCredString(username, password string) string {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil { if err != nil {
@ -141,7 +90,7 @@ func TestNew(t *testing.T) {
func TestObjectStorageController(t *testing.T) { func TestObjectStorageController(t *testing.T) {
skipIt(t) skipIt(t)
Convey("Negative make a new object storage controller", t, func() { Convey("Negative make a new object storage controller", t, func() {
port := getFreePort() port := GetFreePort()
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
storageDriverParams := map[string]interface{}{ storageDriverParams := map[string]interface{}{
@ -159,8 +108,8 @@ func TestObjectStorageController(t *testing.T) {
}) })
Convey("Make a new object storage controller", t, func() { Convey("Make a new object storage controller", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -208,8 +157,8 @@ func TestObjectStorageController(t *testing.T) {
func TestObjectStorageControllerSubPaths(t *testing.T) { func TestObjectStorageControllerSubPaths(t *testing.T) {
skipIt(t) skipIt(t)
Convey("Make a new object storage controller", t, func() { Convey("Make a new object storage controller", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -260,8 +209,8 @@ func TestObjectStorageControllerSubPaths(t *testing.T) {
func TestHtpasswdSingleCred(t *testing.T) { func TestHtpasswdSingleCred(t *testing.T) {
Convey("Single cred", t, func() { Convey("Single cred", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
singleCredtests := []string{} singleCredtests := []string{}
user := ALICE user := ALICE
password := ALICE password := ALICE
@ -273,7 +222,7 @@ func TestHtpasswdSingleCred(t *testing.T) {
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(testString) htpasswdPath := MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -337,11 +286,11 @@ func TestHtpasswdTwoCreds(t *testing.T) {
for _, testString := range twoCredTests { for _, testString := range twoCredTests {
func() { func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(testString) htpasswdPath := MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -406,11 +355,11 @@ func TestHtpasswdFiveCreds(t *testing.T) {
} }
func() { func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(credString.String()) htpasswdPath := MakeHtpasswdFileFromString(credString.String())
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -459,11 +408,11 @@ func TestHtpasswdFiveCreds(t *testing.T) {
} }
func TestBasicAuth(t *testing.T) { func TestBasicAuth(t *testing.T) {
Convey("Make a new controller", t, func() { Convey("Make a new controller", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -521,8 +470,8 @@ func TestBasicAuth(t *testing.T) {
func TestInterruptedBlobUpload(t *testing.T) { func TestInterruptedBlobUpload(t *testing.T) {
Convey("Successfully cleaning interrupted blob uploads", t, func() { Convey("Successfully cleaning interrupted blob uploads", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -761,11 +710,11 @@ func TestInterruptedBlobUpload(t *testing.T) {
func TestMultipleInstance(t *testing.T) { func TestMultipleInstance(t *testing.T) {
Convey("Negative test zot multiple instance", t, func() { Convey("Negative test zot multiple instance", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -783,7 +732,7 @@ func TestMultipleInstance(t *testing.T) {
} }
defer os.RemoveAll(globalDir) defer os.RemoveAll(globalDir)
subDir, err := ioutil.TempDir("/tmp", "oci-sub-test") subDir, err := ioutil.TempDir("", "oci-sub-test")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -823,11 +772,11 @@ func TestMultipleInstance(t *testing.T) {
}) })
Convey("Test zot multiple instance", t, func() { Convey("Test zot multiple instance", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -842,7 +791,7 @@ func TestMultipleInstance(t *testing.T) {
} }
defer os.RemoveAll(globalDir) defer os.RemoveAll(globalDir)
subDir, err := ioutil.TempDir("/tmp", "oci-sub-test") subDir, err := ioutil.TempDir("", "oci-sub-test")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -899,12 +848,12 @@ func TestTLSWithBasicAuth(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -980,12 +929,12 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -1064,9 +1013,9 @@ func TestTLSMutualAuth(t *testing.T) {
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -1152,9 +1101,9 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) {
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -1247,12 +1196,12 @@ func TestTLSMutualAndBasicAuth(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -1345,12 +1294,12 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
caCertPool := x509.NewCertPool() caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
secureBaseURL := getBaseURL(port, true) secureBaseURL := GetSecureBaseURL(port)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool}) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool})
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
@ -1525,8 +1474,8 @@ func TestBasicAuthWithLDAP(t *testing.T) {
l.Start() l.Start()
defer l.Stop() defer l.Stop()
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -1594,8 +1543,8 @@ func TestBearerAuth(t *testing.T) {
authTestServer := makeAuthTestServer() authTestServer := makeAuthTestServer()
defer authTestServer.Close() defer authTestServer.Close()
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -1776,8 +1725,8 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) {
authTestServer := makeAuthTestServer() authTestServer := makeAuthTestServer()
defer authTestServer.Close() defer authTestServer.Close()
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
@ -2010,12 +1959,12 @@ func parseBearerAuthHeader(authHeaderRaw string) *authHeader {
func TestAuthorizationWithBasicAuth(t *testing.T) { func TestAuthorizationWithBasicAuth(t *testing.T) {
Convey("Make a new controller", t, func() { Convey("Make a new controller", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -2047,7 +1996,7 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
panic(err) panic(err)
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
err = copyFiles("../../test/data", dir) err = CopyFiles("../../test/data", dir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -2399,12 +2348,12 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
func TestInvalidCases(t *testing.T) { func TestInvalidCases(t *testing.T) {
Convey("Invalid repo dir", t, func() { Convey("Invalid repo dir", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase)) htpasswdPath := MakeHtpasswdFileFromString(getCredString(username, passphrase))
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
@ -2466,8 +2415,8 @@ func TestHTTPReadOnly(t *testing.T) {
singleCredtests = append(singleCredtests, getCredString(user, password)) singleCredtests = append(singleCredtests, getCredString(user, password))
singleCredtests = append(singleCredtests, getCredString(user, password)+"\n") singleCredtests = append(singleCredtests, getCredString(user, password)+"\n")
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
for _, testString := range singleCredtests { for _, testString := range singleCredtests {
func() { func() {
@ -2476,7 +2425,7 @@ func TestHTTPReadOnly(t *testing.T) {
// enable read-only mode // enable read-only mode
conf.HTTP.ReadOnly = true conf.HTTP.ReadOnly = true
htpasswdPath := makeHtpasswdFileFromString(testString) htpasswdPath := MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -2533,12 +2482,12 @@ func TestHTTPReadOnly(t *testing.T) {
func TestCrossRepoMount(t *testing.T) { func TestCrossRepoMount(t *testing.T) {
Convey("Cross Repo Mount", t, func() { Convey("Cross Repo Mount", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase)) htpasswdPath := MakeHtpasswdFileFromString(getCredString(username, passphrase))
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
@ -2555,7 +2504,7 @@ func TestCrossRepoMount(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../test/data", dir) err = CopyFiles("../../test/data", dir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -2736,12 +2685,12 @@ func TestCrossRepoMount(t *testing.T) {
}) })
Convey("Disable dedupe and cache", t, func() { Convey("Disable dedupe and cache", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase)) htpasswdPath := MakeHtpasswdFileFromString(getCredString(username, passphrase))
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
@ -2760,7 +2709,7 @@ func TestCrossRepoMount(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../test/data", dir) err = CopyFiles("../../test/data", dir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -2797,6 +2746,7 @@ func TestCrossRepoMount(t *testing.T) {
So(headResponse.StatusCode(), ShouldEqual, 404) So(headResponse.StatusCode(), ShouldEqual, 404)
}) })
} }
func TestParallelRequests(t *testing.T) { func TestParallelRequests(t *testing.T) {
testCases := []struct { testCases := []struct {
srcImageName string srcImageName string
@ -2893,12 +2843,12 @@ func TestParallelRequests(t *testing.T) {
}, },
} }
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase)) htpasswdPath := MakeHtpasswdFileFromString(getCredString(username, passphrase))
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -3141,158 +3091,14 @@ func TestParallelRequests(t *testing.T) {
} }
} }
func getAllBlobs(imagePath string) []string {
blobList := make([]string, 0)
if !dirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
blobList = append(blobList, digest.Encoded())
p := path.Join(imagePath, "blobs", digest.Algorithm().String(), digest.Encoded())
buf, err = ioutil.ReadFile(p)
if err != nil {
panic(err)
}
var manifest ispec.Manifest
if err := json.Unmarshal(buf, &manifest); err != nil {
panic(err)
}
blobList = append(blobList, manifest.Config.Digest.Encoded())
for _, layer := range manifest.Layers {
blobList = append(blobList, layer.Digest.Encoded())
}
}
return blobList
}
func getAllManifests(imagePath string) []string {
manifestList := make([]string, 0)
if !dirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
manifestList = append(manifestList, digest.Encoded())
}
return manifestList
}
func dirExists(d string) bool {
fi, err := os.Stat(d)
if err != nil && os.IsNotExist(err) {
return false
}
if !fi.IsDir() {
return false
}
return true
}
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func stopServer(ctrl *api.Controller) {
err := ctrl.Server.Shutdown(context.Background())
if err != nil {
panic(err)
}
err = os.RemoveAll(ctrl.Config.Storage.RootDirectory)
if err != nil {
panic(err)
}
}
func TestHardLink(t *testing.T) { func TestHardLink(t *testing.T) {
Convey("Validate hard link", t, func() { Convey("Validate hard link", t, func() {
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port, false) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase)) htpasswdPath := MakeHtpasswdFileFromString(getCredString(username, passphrase))
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -3363,3 +3169,89 @@ func TestHardLink(t *testing.T) {
So(c.Config.Storage.Dedupe, ShouldEqual, false) So(c.Config.Storage.Dedupe, ShouldEqual, false)
}) })
} }
func getAllBlobs(imagePath string) []string {
blobList := make([]string, 0)
if !storage.DirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
blobList = append(blobList, digest.Encoded())
p := path.Join(imagePath, "blobs", digest.Algorithm().String(), digest.Encoded())
buf, err = ioutil.ReadFile(p)
if err != nil {
panic(err)
}
var manifest ispec.Manifest
if err := json.Unmarshal(buf, &manifest); err != nil {
panic(err)
}
blobList = append(blobList, manifest.Config.Digest.Encoded())
for _, layer := range manifest.Layers {
blobList = append(blobList, layer.Digest.Encoded())
}
}
return blobList
}
func getAllManifests(imagePath string) []string {
manifestList := make([]string, 0)
if !storage.DirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
manifestList = append(manifestList, digest.Encoded())
}
return manifestList
}
func stopServer(ctrl *api.Controller) {
err := ctrl.Server.Shutdown(context.Background())
if err != nil {
panic(err)
}
err = os.RemoveAll(ctrl.Config.Storage.RootDirectory)
if err != nil {
panic(err)
}
}

View file

@ -19,6 +19,7 @@ import (
"time" "time"
zotErrors "github.com/anuvu/zot/errors" zotErrors "github.com/anuvu/zot/errors"
"github.com/anuvu/zot/pkg/storage"
) )
var httpClientsMap = make(map[string]*http.Client) //nolint: gochecknoglobals var httpClientsMap = make(map[string]*http.Client) //nolint: gochecknoglobals
@ -141,7 +142,7 @@ func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config {
home := os.Getenv("HOME") home := os.Getenv("HOME")
clientCertsDir := filepath.Join(home, homeCertsDir, host) clientCertsDir := filepath.Join(home, homeCertsDir, host)
if dirExists(clientCertsDir) { if storage.DirExists(clientCertsDir) {
tlsConfig, err := getTLSConfig(clientCertsDir, caCertPool) tlsConfig, err := getTLSConfig(clientCertsDir, caCertPool)
if err == nil { if err == nil {
@ -151,7 +152,7 @@ func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config {
// Check if the /etc/containers/certs.d/$IP:$PORT dir exists // Check if the /etc/containers/certs.d/$IP:$PORT dir exists
clientCertsDir = filepath.Join(certsPath, host) clientCertsDir = filepath.Join(certsPath, host)
if dirExists(clientCertsDir) { if storage.DirExists(clientCertsDir) {
tlsConfig, err := getTLSConfig(clientCertsDir, caCertPool) tlsConfig, err := getTLSConfig(clientCertsDir, caCertPool)
if err == nil { if err == nil {
@ -185,19 +186,6 @@ func getTLSConfig(certsPath string, caCertPool *x509.CertPool) (*tls.Config, err
}, nil }, nil
} }
func dirExists(d string) bool {
fi, err := os.Stat(d)
if err != nil && os.IsNotExist(err) {
return false
}
if !fi.IsDir() {
return false
}
return true
}
func isURL(str string) bool { func isURL(str string) bool {
u, err := url.Parse(str) u, err := url.Parse(str)
return err == nil && u.Scheme != "" && u.Host != "" return err == nil && u.Scheme != "" && u.Host != ""

View file

@ -8,20 +8,17 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"gopkg.in/resty.v1"
"testing" "testing"
"time" "time"
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
. "github.com/anuvu/zot/test"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
) )
const ( const (
@ -44,21 +41,6 @@ const (
certsDir1 = "/.config/containers/certs.d/127.0.0.1:8088/" certsDir1 = "/.config/containers/certs.d/127.0.0.1:8088/"
) )
func makeHtpasswdFile() string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n")
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func TestTLSWithAuth(t *testing.T) { func TestTLSWithAuth(t *testing.T) {
Convey("Make a new controller", t, func() { Convey("Make a new controller", t, func() {
caCert, err := ioutil.ReadFile(CACert) caCert, err := ioutil.ReadFile(CACert)
@ -70,7 +52,7 @@ func TestTLSWithAuth(t *testing.T) {
defer func() { resty.SetTLSClientConfig(nil) }() defer func() { resty.SetTLSClientConfig(nil) }()
conf := config.New() conf := config.New()
conf.HTTP.Port = SecurePort1 conf.HTTP.Port = SecurePort1
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -119,7 +101,7 @@ func TestTLSWithAuth(t *testing.T) {
home := os.Getenv("HOME") home := os.Getenv("HOME")
destCertsDir := filepath.Join(home, certsDir1) destCertsDir := filepath.Join(home, certsDir1)
if err = copyFiles(sourceCertsDir, destCertsDir); err != nil { if err = CopyFiles(sourceCertsDir, destCertsDir); err != nil {
panic(err) panic(err)
} }
defer os.RemoveAll(destCertsDir) defer os.RemoveAll(destCertsDir)
@ -218,7 +200,7 @@ func TestTLSWithoutAuth(t *testing.T) {
home := os.Getenv("HOME") home := os.Getenv("HOME")
destCertsDir := filepath.Join(home, certsDir1) destCertsDir := filepath.Join(home, certsDir1)
if err = copyFiles(sourceCertsDir, destCertsDir); err != nil { if err = CopyFiles(sourceCertsDir, destCertsDir); err != nil {
panic(err) panic(err)
} }
defer os.RemoveAll(destCertsDir) defer os.RemoveAll(destCertsDir)
@ -359,48 +341,3 @@ func TestTLSBadCerts(t *testing.T) {
}) })
}) })
} }
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}

View file

@ -18,9 +18,9 @@ import (
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
extconf "github.com/anuvu/zot/pkg/extensions/config" extconf "github.com/anuvu/zot/pkg/extensions/config"
"gopkg.in/resty.v1" . "github.com/anuvu/zot/test"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
) )
func TestSearchCVECmd(t *testing.T) { func TestSearchCVECmd(t *testing.T) {
@ -285,8 +285,8 @@ func TestSearchCVECmd(t *testing.T) {
} }
func TestServerCVEResponse(t *testing.T) { func TestServerCVEResponse(t *testing.T) {
port := getFreePort() port := GetFreePort()
url := getBaseURL(port) url := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
c := api.NewController(conf) c := api.NewController(conf)
@ -296,7 +296,7 @@ func TestServerCVEResponse(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../test/data/zot-cve-test", path.Join(dir, "zot-cve-test")) err = CopyFiles("../../test/data/zot-cve-test", path.Join(dir, "zot-cve-test"))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -13,40 +13,20 @@ import (
"regexp" "regexp"
"strings" "strings"
"sync" "sync"
"gopkg.in/resty.v1"
"testing" "testing"
"time" "time"
zotErrors "github.com/anuvu/zot/errors" zotErrors "github.com/anuvu/zot/errors"
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
"github.com/anuvu/zot/pkg/compliance/v1_0_0"
extconf "github.com/anuvu/zot/pkg/extensions/config" extconf "github.com/anuvu/zot/pkg/extensions/config"
. "github.com/anuvu/zot/test"
godigest "github.com/opencontainers/go-digest" godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/phayes/freeport"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
) )
const (
BaseURL = "http://127.0.0.1:%s"
)
func getBaseURL(port string) string {
return fmt.Sprintf(BaseURL, port)
}
func getFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func TestSearchImageCmd(t *testing.T) { func TestSearchImageCmd(t *testing.T) {
Convey("Test image help", t, func() { Convey("Test image help", t, func() {
args := []string{"--help"} args := []string{"--help"}
@ -301,8 +281,8 @@ func TestOutputFormat(t *testing.T) {
func TestServerResponse(t *testing.T) { func TestServerResponse(t *testing.T) {
Convey("Test from real server", t, func() { Convey("Test from real server", t, func() {
port := getFreePort() port := GetFreePort()
url := getBaseURL(port) url := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
conf.Extensions = &extconf.ExtensionConfig{ conf.Extensions = &extconf.ExtensionConfig{
@ -481,7 +461,7 @@ func TestServerResponse(t *testing.T) {
func uploadManifest(url string) { func uploadManifest(url string) {
// create a blob/layer // create a blob/layer
resp, _ := resty.R().Post(url + "/v2/repo7/blobs/uploads/") resp, _ := resty.R().Post(url + "/v2/repo7/blobs/uploads/")
loc := v1_0_0.Location(url, resp) loc := Location(url, resp)
content := []byte("this is a blob5") content := []byte("this is a blob5")
digest := godigest.FromBytes(content) digest := godigest.FromBytes(content)

View file

@ -13,6 +13,7 @@ import (
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/compliance" "github.com/anuvu/zot/pkg/compliance"
. "github.com/anuvu/zot/test" // nolint:golint,stylecheck
godigest "github.com/opencontainers/go-digest" godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey" // nolint:golint,stylecheck . "github.com/smartystreets/goconvey/convey" // nolint:golint,stylecheck
@ -20,20 +21,6 @@ import (
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
func Location(baseURL string, resp *resty.Response) string {
// For some API responses, the Location header is set and is supposed to
// indicate an opaque value. However, it is not clear if this value is an
// absolute URL (https://server:port/v2/...) or just a path (/v2/...)
// zot implements the latter as per the spec, but some registries appear to
// return the former - this needs to be clarified
loc := resp.Header().Get("Location")
if loc[0] == '/' {
return baseURL + loc
}
return loc
}
func CheckWorkflows(t *testing.T, config *compliance.Config) { func CheckWorkflows(t *testing.T, config *compliance.Config) {
if config == nil || config.Address == "" || config.Port == "" { if config == nil || config.Address == "" || config.Port == "" {
panic("insufficient config") panic("insufficient config")

View file

@ -2,8 +2,8 @@ package v1_0_0_test
import ( import (
"context" "context"
"fmt"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"testing" "testing"
"time" "time"
@ -12,7 +12,7 @@ import (
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
"github.com/anuvu/zot/pkg/compliance" "github.com/anuvu/zot/pkg/compliance"
"github.com/anuvu/zot/pkg/compliance/v1_0_0" "github.com/anuvu/zot/pkg/compliance/v1_0_0"
"github.com/phayes/freeport" . "github.com/anuvu/zot/test"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
@ -53,17 +53,11 @@ func TestWorkflowsOutputJSON(t *testing.T) {
// start local server on random open port. // start local server on random open port.
func startServer() (*api.Controller, string) { func startServer() (*api.Controller, string) {
portInt, err := freeport.GetFreePort() port := GetFreePort()
if err != nil { baseURL := GetBaseURL(port)
panic(err)
}
randomPort := fmt.Sprintf("%d", portInt)
fmt.Println(randomPort)
conf := config.New() conf := config.New()
conf.HTTP.Address = listenAddress conf.HTTP.Address = listenAddress
conf.HTTP.Port = randomPort conf.HTTP.Port = port
ctrl := api.NewController(conf) ctrl := api.NewController(conf)
dir, err := ioutil.TempDir("", "oci-repo-test") dir, err := ioutil.TempDir("", "oci-repo-test")
@ -103,19 +97,17 @@ func startServer() (*api.Controller, string) {
} }
}() }()
baseURL := fmt.Sprintf("http://%s:%s", listenAddress, randomPort)
for { for {
// poll until ready // poll until ready
resp, _ := resty.R().Get(baseURL) resp, _ := resty.R().Get(baseURL)
if resp.StatusCode() == 404 { if resp.StatusCode() == http.StatusNotFound {
break break
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
return ctrl, randomPort return ctrl, port
} }
func stopServer(ctrl *api.Controller) { func stopServer(ctrl *api.Controller) {

View file

@ -19,8 +19,8 @@ import (
zotcfg "github.com/anuvu/zot/pkg/api/config" zotcfg "github.com/anuvu/zot/pkg/api/config"
"github.com/anuvu/zot/pkg/exporter/api" "github.com/anuvu/zot/pkg/exporter/api"
"github.com/anuvu/zot/pkg/extensions/monitoring" "github.com/anuvu/zot/pkg/extensions/monitoring"
. "github.com/anuvu/zot/test"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/phayes/freeport"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
@ -28,7 +28,6 @@ import (
) )
const ( const (
BaseURL = "http://127.0.0.1:%s"
SleepTime = 50 * time.Millisecond SleepTime = 50 * time.Millisecond
SecondToNanoseconds = 1000000000 SecondToNanoseconds = 1000000000
) )
@ -42,15 +41,6 @@ func getRandomLatency() time.Duration {
return getRandomLatencyN(120 * SecondToNanoseconds) // a random latency (in nanoseconds) that can be up to 2 minutes return getRandomLatencyN(120 * SecondToNanoseconds) // a random latency (in nanoseconds) that can be up to 2 minutes
} }
func getFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
Convey("Make a new controller", t, func() { Convey("Make a new controller", t, func() {
config := api.DefaultConfig() config := api.DefaultConfig()
@ -91,8 +81,8 @@ func TestNewExporter(t *testing.T) {
Convey("Make an exporter controller", t, func() { Convey("Make an exporter controller", t, func() {
exporterConfig := api.DefaultConfig() exporterConfig := api.DefaultConfig()
So(exporterConfig, ShouldNotBeNil) So(exporterConfig, ShouldNotBeNil)
exporterPort := getFreePort() exporterPort := GetFreePort()
serverPort := getFreePort() serverPort := GetFreePort()
exporterConfig.Exporter.Port = exporterPort exporterConfig.Exporter.Port = exporterPort
dir, _ := ioutil.TempDir("", "metrics") dir, _ := ioutil.TempDir("", "metrics")
exporterConfig.Exporter.Metrics.Path = strings.TrimPrefix(dir, "/tmp/") exporterConfig.Exporter.Metrics.Path = strings.TrimPrefix(dir, "/tmp/")

View file

@ -5,7 +5,6 @@ package common_test
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -19,6 +18,7 @@ import (
"github.com/anuvu/zot/pkg/extensions/search/common" "github.com/anuvu/zot/pkg/extensions/search/common"
"github.com/anuvu/zot/pkg/log" "github.com/anuvu/zot/pkg/log"
"github.com/anuvu/zot/pkg/storage" "github.com/anuvu/zot/pkg/storage"
. "github.com/anuvu/zot/test"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
@ -30,11 +30,6 @@ var (
subRootDir string subRootDir string
) )
const (
BaseURL1 = "http://127.0.0.1:8085"
Port1 = "8085"
)
type ImgResponsWithLatestTag struct { type ImgResponsWithLatestTag struct {
ImgListWithLatestTag ImgListWithLatestTag `json:"data"` ImgListWithLatestTag ImgListWithLatestTag `json:"data"`
Errors []ErrorGQL `json:"errors"` Errors []ErrorGQL `json:"errors"`
@ -75,12 +70,12 @@ func testSetup() error {
subRootDir = subDir subRootDir = subDir
err = copyFiles("../../../../test/data", rootDir) err = CopyFiles("../../../../test/data", rootDir)
if err != nil { if err != nil {
return err return err
} }
err = copyFiles("../../../../test/data", subDir) err = CopyFiles("../../../../test/data", subDir)
if err != nil { if err != nil {
return err return err
} }
@ -112,51 +107,6 @@ func getTags() ([]common.TagInfo, []common.TagInfo) {
return tags, infectedTags return tags, infectedTags
} }
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func TestImageFormat(t *testing.T) { func TestImageFormat(t *testing.T) {
Convey("Test valid image", t, func() { Convey("Test valid image", t, func() {
log := log.NewLogger("debug", "") log := log.NewLogger("debug", "")
@ -219,8 +169,10 @@ func TestLatestTagSearchHTTP(t *testing.T) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = Port1 conf.HTTP.Port = port
conf.Storage.RootDirectory = rootDir conf.Storage.RootDirectory = rootDir
conf.Storage.SubPaths = make(map[string]config.StorageConfig) conf.Storage.SubPaths = make(map[string]config.StorageConfig)
conf.Storage.SubPaths["/a"] = config.StorageConfig{RootDirectory: subRootDir} conf.Storage.SubPaths["/a"] = config.StorageConfig{RootDirectory: subRootDir}
@ -241,7 +193,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
// wait till ready // wait till ready
for { for {
_, err := resty.R().Get(BaseURL1) _, err := resty.R().Get(baseURL)
if err == nil { if err == nil {
break break
} }
@ -254,17 +206,17 @@ func TestLatestTagSearchHTTP(t *testing.T) {
_ = c.Server.Shutdown(ctx) _ = c.Server.Shutdown(ctx)
}() }()
resp, err := resty.R().Get(BaseURL1 + "/v2/") resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query") resp, err = resty.R().Get(baseURL + "/query")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -277,7 +229,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
images := responseStruct.ImgListWithLatestTag.Images images := responseStruct.ImgListWithLatestTag.Images
So(images[0].Latest, ShouldEqual, "0.0.1") So(images[0].Latest, ShouldEqual, "0.0.1")
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
@ -286,7 +238,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
panic(err) panic(err)
} }
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -307,7 +259,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
panic(err) panic(err)
} }
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -318,7 +270,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
panic(err) panic(err)
} }
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -329,7 +281,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
panic(err) panic(err)
} }
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -341,7 +293,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
panic(err) panic(err)
} }
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListWithLatestTag(){Name%20Latest}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)

View file

@ -7,7 +7,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -22,8 +21,8 @@ import (
cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve" cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve"
"github.com/anuvu/zot/pkg/log" "github.com/anuvu/zot/pkg/log"
"github.com/anuvu/zot/pkg/storage" "github.com/anuvu/zot/pkg/storage"
. "github.com/anuvu/zot/test"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/phayes/freeport"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
@ -36,7 +35,6 @@ var (
) )
const ( const (
BaseURL = "http://127.0.0.1:%s"
username = "test" username = "test"
passphrase = "test" passphrase = "test"
) )
@ -77,19 +75,6 @@ type CVE struct {
Severity string `json:"Severity"` Severity string `json:"Severity"`
} }
func getFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func getBaseURL(port string) string {
return fmt.Sprintf(BaseURL, port)
}
func testSetup() error { func testSetup() error {
dir, err := ioutil.TempDir("", "util_test") dir, err := ioutil.TempDir("", "util_test")
if err != nil { if err != nil {
@ -112,7 +97,7 @@ func testSetup() error {
return err return err
} }
err = copyFiles("../../../../test/data", dbDir) err = CopyFiles("../../../../test/data", dbDir)
if err != nil { if err != nil {
return err return err
} }
@ -122,12 +107,12 @@ func testSetup() error {
func generateTestData() error { // nolint: gocyclo func generateTestData() error { // nolint: gocyclo
// Image dir with no files // Image dir with no files
err := os.Mkdir(path.Join(dbDir, "zot-noindex-test"), 0o755) err := os.Mkdir(path.Join(dbDir, "zot-noindex-test"), 0755)
if err != nil { if err != nil {
return err return err
} }
err = os.Mkdir(path.Join(dbDir, "zot-nonreadable-test"), 0o755) err = os.Mkdir(path.Join(dbDir, "zot-nonreadable-test"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -140,12 +125,12 @@ func generateTestData() error { // nolint: gocyclo
return err return err
} }
if err = ioutil.WriteFile(path.Join(dbDir, "zot-nonreadable-test", "index.json"), buf, 0o111); err != nil { if err = ioutil.WriteFile(path.Join(dbDir, "zot-nonreadable-test", "index.json"), buf, 0111); err != nil {
return err return err
} }
// Image dir with invalid index.json // Image dir with invalid index.json
err = os.Mkdir(path.Join(dbDir, "zot-squashfs-invalid-index"), 0o755) err = os.Mkdir(path.Join(dbDir, "zot-squashfs-invalid-index"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -158,7 +143,7 @@ func generateTestData() error { // nolint: gocyclo
} }
// Image dir with no blobs // Image dir with no blobs
err = os.Mkdir(path.Join(dbDir, "zot-squashfs-noblobs"), 0o755) err = os.Mkdir(path.Join(dbDir, "zot-squashfs-noblobs"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -172,7 +157,7 @@ func generateTestData() error { // nolint: gocyclo
} }
// Image dir with invalid blob // Image dir with invalid blob
err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256"), 0o755) err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -195,7 +180,7 @@ func generateTestData() error { // nolint: gocyclo
// Create a squashfs image // Create a squashfs image
err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256"), 0o755) err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -207,11 +192,11 @@ func generateTestData() error { // nolint: gocyclo
return err return err
} }
if err = ioutil.WriteFile(path.Join(dbDir, "zot-squashfs-test", "oci-layout"), buf, 0o644); err != nil { //nolint: gosec if err = ioutil.WriteFile(path.Join(dbDir, "zot-squashfs-test", "oci-layout"), buf, 0644); err != nil { //nolint: gosec
return err return err
} }
err = os.Mkdir(path.Join(dbDir, "zot-squashfs-test", ".uploads"), 0o755) err = os.Mkdir(path.Join(dbDir, "zot-squashfs-test", ".uploads"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -267,7 +252,7 @@ func generateTestData() error { // nolint: gocyclo
// Create a image with invalid layer blob // Create a image with invalid layer blob
err = os.MkdirAll(path.Join(dbDir, "zot-invalid-layer", "blobs/sha256"), 0o755) err = os.MkdirAll(path.Join(dbDir, "zot-invalid-layer", "blobs/sha256"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -295,7 +280,7 @@ func generateTestData() error { // nolint: gocyclo
// Create a image with no layer blob // Create a image with no layer blob
err = os.MkdirAll(path.Join(dbDir, "zot-no-layer", "blobs/sha256"), 0o755) err = os.MkdirAll(path.Join(dbDir, "zot-no-layer", "blobs/sha256"), 0755)
if err != nil { if err != nil {
return err return err
} }
@ -325,73 +310,13 @@ func generateTestData() error { // nolint: gocyclo
} }
func makeTestFile(fileName string, content string) error { func makeTestFile(fileName string, content string) error {
if err := ioutil.WriteFile(fileName, []byte(content), 0o600); err != nil { if err := ioutil.WriteFile(fileName, []byte(content), 0600); err != nil {
panic(err) panic(err)
} }
return nil return nil
} }
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func makeHtpasswdFile() string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n")
if err := ioutil.WriteFile(f.Name(), content, 0o600); err != nil {
panic(err)
}
return f.Name()
}
func TestMultipleStoragePath(t *testing.T) { func TestMultipleStoragePath(t *testing.T) {
Convey("Test multiple storage path", t, func() { Convey("Test multiple storage path", t, func() {
// Create temporary directory // Create temporary directory
@ -452,11 +377,11 @@ func TestDownloadDB(t *testing.T) {
func TestCVESearch(t *testing.T) { func TestCVESearch(t *testing.T) {
Convey("Test image vulenrability scanning", t, func() { Convey("Test image vulenrability scanning", t, func() {
updateDuration, _ = time.ParseDuration("1h") updateDuration, _ = time.ParseDuration("1h")
port := getFreePort() port := GetFreePort()
baseURL := getBaseURL(port) baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = port conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -680,10 +605,10 @@ func TestCVESearch(t *testing.T) {
func TestCVEConfig(t *testing.T) { func TestCVEConfig(t *testing.T) {
Convey("Verify CVE config", t, func() { Convey("Verify CVE config", t, func() {
conf := config.New() conf := config.New()
port := getFreePort() port := GetFreePort()
conf.HTTP.Port = port conf.HTTP.Port = port
baseURL := getBaseURL(port) baseURL := GetBaseURL(port)
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
@ -704,7 +629,7 @@ func TestCVEConfig(t *testing.T) {
defer os.RemoveAll(firstDir) defer os.RemoveAll(firstDir)
defer os.RemoveAll(secondDir) defer os.RemoveAll(secondDir)
err = copyFiles("../../../../test/data", path.Join(secondDir, "a")) err = CopyFiles("../../../../test/data", path.Join(secondDir, "a"))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -6,10 +6,8 @@ package digestinfo_test
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"testing" "testing"
"time" "time"
@ -20,6 +18,7 @@ import (
digestinfo "github.com/anuvu/zot/pkg/extensions/search/digest" digestinfo "github.com/anuvu/zot/pkg/extensions/search/digest"
"github.com/anuvu/zot/pkg/log" "github.com/anuvu/zot/pkg/log"
"github.com/anuvu/zot/pkg/storage" "github.com/anuvu/zot/pkg/storage"
. "github.com/anuvu/zot/test"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
@ -31,11 +30,6 @@ var (
subRootDir string subRootDir string
) )
const (
BaseURL1 = "http://127.0.0.1:8085"
Port1 = "8085"
)
type ImgResponseForDigest struct { type ImgResponseForDigest struct {
ImgListForDigest ImgListForDigest `json:"data"` ImgListForDigest ImgListForDigest `json:"data"`
Errors []ErrorGQL `json:"errors"` Errors []ErrorGQL `json:"errors"`
@ -89,12 +83,12 @@ func testSetup() error {
return err return err
} }
err = copyFiles("../../../../test/data", rootDir) err = CopyFiles("../../../../test/data", rootDir)
if err != nil { if err != nil {
return err return err
} }
err = copyFiles("../../../../test/data", subDir+"/a/") err = CopyFiles("../../../../test/data", subDir+"/a/")
if err != nil { if err != nil {
return err return err
} }
@ -108,51 +102,6 @@ func testSetup() error {
return nil return nil
} }
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func TestDigestInfo(t *testing.T) { func TestDigestInfo(t *testing.T) {
Convey("Test image tag", t, func() { Convey("Test image tag", t, func() {
// Search by manifest digest // Search by manifest digest
@ -187,8 +136,10 @@ func TestDigestInfo(t *testing.T) {
func TestDigestSearchHTTP(t *testing.T) { func TestDigestSearchHTTP(t *testing.T) {
Convey("Test image search by digest scanning", t, func() { Convey("Test image search by digest scanning", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = Port1 conf.HTTP.Port = port
conf.Storage.RootDirectory = rootDir conf.Storage.RootDirectory = rootDir
conf.Extensions = &extconf.ExtensionConfig{ conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{Enable: true}, Search: &extconf.SearchConfig{Enable: true},
@ -205,7 +156,7 @@ func TestDigestSearchHTTP(t *testing.T) {
// wait till ready // wait till ready
for { for {
_, err := resty.R().Get(BaseURL1) _, err := resty.R().Get(baseURL)
if err == nil { if err == nil {
break break
} }
@ -218,18 +169,18 @@ func TestDigestSearchHTTP(t *testing.T) {
_ = c.Server.Shutdown(ctx) _ = c.Server.Shutdown(ctx)
}() }()
resp, err := resty.R().Get(BaseURL1 + "/v2/") resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query") resp, err = resty.R().Get(baseURL + "/query")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
// "sha" should match all digests in all images // "sha" should match all digests in all images
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -244,7 +195,7 @@ func TestDigestSearchHTTP(t *testing.T) {
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}} // Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
// "2bacca16" should match the manifest of 1 image // "2bacca16" should match the manifest of 1 image
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"2bacca16\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"2bacca16\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -259,7 +210,7 @@ func TestDigestSearchHTTP(t *testing.T) {
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}} // Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
// "adf3bb6c" should match the config of 1 image // "adf3bb6c" should match the config of 1 image
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"adf3bb6c\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"adf3bb6c\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -274,7 +225,7 @@ func TestDigestSearchHTTP(t *testing.T) {
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-cve-test","Tags":["0.0.1"]}]}} // Call should return {"data":{"ImageListForDigest":[{"Name":"zot-cve-test","Tags":["0.0.1"]}]}}
// "7a0437f0" should match the layer of 1 image // "7a0437f0" should match the layer of 1 image
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"7a0437f0\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"7a0437f0\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -289,7 +240,7 @@ func TestDigestSearchHTTP(t *testing.T) {
// Call should return {"data":{"ImageListForDigest":[]}} // Call should return {"data":{"ImageListForDigest":[]}}
// "1111111" should match 0 images // "1111111" should match 0 images
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -300,7 +251,7 @@ func TestDigestSearchHTTP(t *testing.T) {
So(len(responseStruct.ImgListForDigest.Images), ShouldEqual, 0) So(len(responseStruct.ImgListForDigest.Images), ShouldEqual, 0)
// Call should return {"errors": [{....}]", data":null}} // Call should return {"errors": [{....}]", data":null}}
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tag343s}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tag343s}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 422) So(resp.StatusCode(), ShouldEqual, 422)
@ -313,8 +264,10 @@ func TestDigestSearchHTTP(t *testing.T) {
func TestDigestSearchHTTPSubPaths(t *testing.T) { func TestDigestSearchHTTPSubPaths(t *testing.T) {
Convey("Test image search by digest scanning using storage subpaths", t, func() { Convey("Test image search by digest scanning using storage subpaths", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = Port1 conf.HTTP.Port = port
conf.Extensions = &extconf.ExtensionConfig{ conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{Enable: true}, Search: &extconf.SearchConfig{Enable: true},
} }
@ -344,7 +297,7 @@ func TestDigestSearchHTTPSubPaths(t *testing.T) {
// wait till ready // wait till ready
for { for {
_, err := resty.R().Get(BaseURL1) _, err := resty.R().Get(baseURL)
if err == nil { if err == nil {
break break
} }
@ -357,17 +310,17 @@ func TestDigestSearchHTTPSubPaths(t *testing.T) {
_ = c.Server.Shutdown(ctx) _ = c.Server.Shutdown(ctx)
}() }()
resp, err := resty.R().Get(BaseURL1 + "/v2/") resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query") resp, err = resty.R().Get(baseURL + "/query")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}") resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
@ -384,8 +337,10 @@ func TestDigestSearchDisabled(t *testing.T) {
Convey("Test disabling image search", t, func() { Convey("Test disabling image search", t, func() {
dir, err := ioutil.TempDir("", "digest_test") dir, err := ioutil.TempDir("", "digest_test")
So(err, ShouldBeNil) So(err, ShouldBeNil)
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
conf.HTTP.Port = Port1 conf.HTTP.Port = port
conf.Storage.RootDirectory = dir conf.Storage.RootDirectory = dir
conf.Extensions = &extconf.ExtensionConfig{ conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{Enable: false}, Search: &extconf.SearchConfig{Enable: false},
@ -402,7 +357,7 @@ func TestDigestSearchDisabled(t *testing.T) {
// wait till ready // wait till ready
for { for {
_, err := resty.R().Get(BaseURL1) _, err := resty.R().Get(baseURL)
if err == nil { if err == nil {
break break
} }
@ -415,12 +370,12 @@ func TestDigestSearchDisabled(t *testing.T) {
_ = c.Server.Shutdown(ctx) _ = c.Server.Shutdown(ctx)
}() }()
resp, err := resty.R().Get(BaseURL1 + "/v2/") resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200) So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(BaseURL1 + "/query") resp, err = resty.R().Get(baseURL + "/query")
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404) So(resp.StatusCode(), ShouldEqual, 404)

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -15,6 +14,7 @@ import (
"github.com/anuvu/zot/pkg/extensions/monitoring" "github.com/anuvu/zot/pkg/extensions/monitoring"
"github.com/anuvu/zot/pkg/log" "github.com/anuvu/zot/pkg/log"
"github.com/anuvu/zot/pkg/storage" "github.com/anuvu/zot/pkg/storage"
. "github.com/anuvu/zot/test"
"github.com/containers/image/v5/docker" "github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
@ -25,62 +25,12 @@ import (
) )
const ( const (
BaseURL = "http://127.0.0.1:5001"
ServerCert = "../../../test/data/server.cert"
ServerKey = "../../../test/data/server.key"
CACert = "../../../test/data/ca.crt"
testImage = "zot-test" testImage = "zot-test"
testImageTag = "0.0.1" testImageTag = "0.0.1"
host = "127.0.0.1:45117" host = "127.0.0.1:45117"
) )
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func TestSyncInternal(t *testing.T) { func TestSyncInternal(t *testing.T) {
Convey("Verify parseRepositoryReference func", t, func() { Convey("Verify parseRepositoryReference func", t, func() {
repositoryReference := fmt.Sprintf("%s/%s", host, testImage) repositoryReference := fmt.Sprintf("%s/%s", host, testImage)
@ -135,13 +85,15 @@ func TestSyncInternal(t *testing.T) {
var tlsVerify bool var tlsVerify bool
updateDuration := time.Microsecond updateDuration := time.Microsecond
port := GetFreePort()
baseURL := GetBaseURL(port)
syncRegistryConfig := RegistryConfig{ syncRegistryConfig := RegistryConfig{
Content: []Content{ Content: []Content{
{ {
Prefix: testImage, Prefix: testImage,
}, },
}, },
URL: BaseURL, URL: baseURL,
PollInterval: updateDuration, PollInterval: updateDuration,
TLSVerify: &tlsVerify, TLSVerify: &tlsVerify,
CertDir: "", CertDir: "",
@ -243,7 +195,7 @@ func TestSyncInternal(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../../test/data", testRootDir) err = CopyFiles("../../../test/data", testRootDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -22,20 +22,18 @@ import (
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
extconf "github.com/anuvu/zot/pkg/extensions/config" extconf "github.com/anuvu/zot/pkg/extensions/config"
"github.com/anuvu/zot/pkg/extensions/sync" "github.com/anuvu/zot/pkg/extensions/sync"
. "github.com/anuvu/zot/test"
ispec "github.com/opencontainers/image-spec/specs-go/v1" ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/phayes/freeport"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
const ( const (
BaseURL = "http://127.0.0.1:%s" ServerCert = "../../../test/data/server.cert"
BaseSecureURL = "https://127.0.0.1:%s" ServerKey = "../../../test/data/server.key"
ServerCert = "../../../test/data/server.cert" CACert = "../../../test/data/ca.crt"
ServerKey = "../../../test/data/server.key" ClientCert = "../../../test/data/client.cert"
CACert = "../../../test/data/ca.crt" ClientKey = "../../../test/data/client.key"
ClientCert = "../../../test/data/client.cert"
ClientKey = "../../../test/data/client.key"
testImage = "zot-test" testImage = "zot-test"
testImageTag = "0.0.1" testImageTag = "0.0.1"
@ -53,23 +51,6 @@ type catalog struct {
Repositories []string `json:"repositories"` Repositories []string `json:"repositories"`
} }
func getFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func getBaseURL(port string, secure bool) string {
if secure {
return fmt.Sprintf(BaseSecureURL, port)
}
return fmt.Sprintf(BaseURL, port)
}
func copyFile(sourceFilePath, destFilePath string) error { func copyFile(sourceFilePath, destFilePath string) error {
destFile, err := os.Create(destFilePath) destFile, err := os.Create(destFilePath)
if err != nil { if err != nil {
@ -90,72 +71,12 @@ func copyFile(sourceFilePath, destFilePath string) error {
return nil return nil
} }
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func makeHtpasswdFile() string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n")
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func TestSyncOnDemand(t *testing.T) { func TestSyncOnDemand(t *testing.T) {
Convey("Verify sync on demand feature", t, func() { Convey("Verify sync on demand feature", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -167,7 +88,7 @@ func TestSyncOnDemand(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -198,8 +119,8 @@ func TestSyncOnDemand(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -357,8 +278,8 @@ func TestSync(t *testing.T) {
Convey("Verify sync feature", t, func() { Convey("Verify sync feature", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -370,7 +291,7 @@ func TestSync(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -401,8 +322,8 @@ func TestSync(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -505,8 +426,8 @@ func TestSync(t *testing.T) {
}) })
Convey("Test sync with more contents", func() { Convey("Test sync with more contents", func() {
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -625,8 +546,8 @@ func TestSyncPermsDenied(t *testing.T) {
Convey("Verify sync feature without perm on sync cache", t, func() { Convey("Verify sync feature without perm on sync cache", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -638,7 +559,7 @@ func TestSyncPermsDenied(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -669,8 +590,8 @@ func TestSyncPermsDenied(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -759,8 +680,8 @@ func TestSyncBadTLS(t *testing.T) {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, true) srcBaseURL := GetSecureBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -814,15 +735,15 @@ func TestSyncBadTLS(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../../test/data", destDir) err = CopyFiles("../../../test/data", destDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer os.RemoveAll(destDir) defer os.RemoveAll(destDir)
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, true) destBaseURL := GetSecureBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -906,8 +827,8 @@ func TestSyncTLS(t *testing.T) {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, true) srcBaseURL := GetSecureBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -925,7 +846,7 @@ func TestSyncTLS(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -971,8 +892,8 @@ func TestSyncTLS(t *testing.T) {
panic(err) panic(err)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, true) destBaseURL := GetSecureBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1090,13 +1011,13 @@ func TestSyncBasicAuth(t *testing.T) {
Convey("Verify sync basic auth", t, func() { Convey("Verify sync basic auth", t, func() {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
srcConfig.HTTP.Auth = &config.AuthConfig{ srcConfig.HTTP.Auth = &config.AuthConfig{
@ -1112,7 +1033,7 @@ func TestSyncBasicAuth(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1145,8 +1066,8 @@ func TestSyncBasicAuth(t *testing.T) {
} }
Convey("Verify sync basic auth with file credentials", func() { Convey("Verify sync basic auth with file credentials", func() {
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1243,8 +1164,8 @@ func TestSyncBasicAuth(t *testing.T) {
}) })
Convey("Verify sync basic auth with wrong file credentials", func() { Convey("Verify sync basic auth with wrong file credentials", func() {
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1335,8 +1256,8 @@ func TestSyncBasicAuth(t *testing.T) {
}) })
Convey("Verify sync basic auth with bad file credentials", func() { Convey("Verify sync basic auth with bad file credentials", func() {
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1425,8 +1346,8 @@ func TestSyncBasicAuth(t *testing.T) {
}) })
Convey("Verify on demand sync with basic auth", func() { Convey("Verify on demand sync with basic auth", func() {
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1552,8 +1473,8 @@ func TestSyncBadUrl(t *testing.T) {
Convey("Verify sync with bad url", t, func() { Convey("Verify sync with bad url", t, func() {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1627,8 +1548,8 @@ func TestSyncNoImagesByRegex(t *testing.T) {
Convey("Verify sync with no images on source based on regex", t, func() { Convey("Verify sync with no images on source based on regex", t, func() {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -1638,7 +1559,7 @@ func TestSyncNoImagesByRegex(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1671,8 +1592,8 @@ func TestSyncNoImagesByRegex(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1758,8 +1679,8 @@ func TestSyncInvalidRegex(t *testing.T) {
Convey("Verify sync with invalid regex", t, func() { Convey("Verify sync with invalid regex", t, func() {
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -1769,7 +1690,7 @@ func TestSyncInvalidRegex(t *testing.T) {
panic(err) panic(err)
} }
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1802,8 +1723,8 @@ func TestSyncInvalidRegex(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -1876,8 +1797,8 @@ func TestSyncNotSemver(t *testing.T) {
Convey("Verify sync feature semver compliant", t, func() { Convey("Verify sync feature semver compliant", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -1889,7 +1810,7 @@ func TestSyncNotSemver(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -1935,8 +1856,8 @@ func TestSyncNotSemver(t *testing.T) {
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, 201) So(resp.StatusCode(), ShouldEqual, 201)
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -2032,8 +1953,8 @@ func TestSyncInvalidCerts(t *testing.T) {
defer func() { client.SetTLSClientConfig(nil) }() defer func() { client.SetTLSClientConfig(nil) }()
updateDuration, _ := time.ParseDuration("1h") updateDuration, _ := time.ParseDuration("1h")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, true) srcBaseURL := GetSecureBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -2051,7 +1972,7 @@ func TestSyncInvalidCerts(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -2088,8 +2009,8 @@ func TestSyncInvalidCerts(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -2208,8 +2129,8 @@ func TestSyncInvalidUrl(t *testing.T) {
Convey("Verify sync invalid url", t, func() { Convey("Verify sync invalid url", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort
@ -2283,8 +2204,8 @@ func TestSyncInvalidTags(t *testing.T) {
Convey("Verify sync invalid url", t, func() { Convey("Verify sync invalid url", t, func() {
updateDuration, _ := time.ParseDuration("30m") updateDuration, _ := time.ParseDuration("30m")
srcPort := getFreePort() srcPort := GetFreePort()
srcBaseURL := getBaseURL(srcPort, false) srcBaseURL := GetBaseURL(srcPort)
srcConfig := config.New() srcConfig := config.New()
srcConfig.HTTP.Port = srcPort srcConfig.HTTP.Port = srcPort
@ -2296,7 +2217,7 @@ func TestSyncInvalidTags(t *testing.T) {
defer os.RemoveAll(srcDir) defer os.RemoveAll(srcDir)
err = copyFiles("../../../test/data", srcDir) err = CopyFiles("../../../test/data", srcDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -2326,8 +2247,8 @@ func TestSyncInvalidTags(t *testing.T) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
destPort := getFreePort() destPort := GetFreePort()
destBaseURL := getBaseURL(destPort, false) destBaseURL := GetBaseURL(destPort)
destConfig := config.New() destConfig := config.New()
destConfig.HTTP.Port = destPort destConfig.HTTP.Port = destPort

View file

@ -7,28 +7,24 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
"path"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/anuvu/zot/pkg/api" "github.com/anuvu/zot/pkg/api"
"github.com/anuvu/zot/pkg/api/config" "github.com/anuvu/zot/pkg/api/config"
. "github.com/anuvu/zot/test"
godigest "github.com/opencontainers/go-digest" godigest "github.com/opencontainers/go-digest"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
) )
const ( const (
BaseURL = "http://127.0.0.1:8086"
SecurePort = "8086"
username = "test" username = "test"
passphrase = "test" passphrase = "test"
ServerCert = "../../test/data/server.cert"
AuthorizedNamespace = "everyone/isallowed" AuthorizedNamespace = "everyone/isallowed"
UnauthorizedNamespace = "fortknox/notallowed" UnauthorizedNamespace = "fortknox/notallowed"
) )
@ -44,80 +40,6 @@ type AuditLog struct {
Message string `json:"message"` Message string `json:"message"`
} }
func makeHtpasswdFile() string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n")
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}
func Location(baseURL string, resp *resty.Response) string {
// For some API responses, the Location header is set and is supposed to
// indicate an opaque value. However, it is not clear if this value is an
// absolute URL (https://server:port/v2/...) or just a path (/v2/...)
// zot implements the latter as per the spec, but some registries appear to
// return the former - this needs to be clarified
loc := resp.Header().Get("Location")
if loc[0] == '/' {
return baseURL + loc
}
return loc
}
func TestAuditLogMessages(t *testing.T) { func TestAuditLogMessages(t *testing.T) {
Convey("Make a new controller", t, func() { Convey("Make a new controller", t, func() {
dir, err := ioutil.TempDir("", "oci-repo-test") dir, err := ioutil.TempDir("", "oci-repo-test")
@ -125,20 +47,22 @@ func TestAuditLogMessages(t *testing.T) {
panic(err) panic(err)
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
err = copyFiles("../../test/data", dir) err = CopyFiles("../../test/data", dir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New() conf := config.New()
outputPath := dir + "/zot.log" outputPath := dir + "/zot.log"
auditPath := dir + "/zot-audit.log" auditPath := dir + "/zot-audit.log"
conf.Log = &config.LogConfig{Level: "debug", Output: outputPath, Audit: auditPath} conf.Log = &config.LogConfig{Level: "debug", Output: outputPath, Audit: auditPath}
conf.HTTP.Port = SecurePort conf.HTTP.Port = port
htpasswdPath := makeHtpasswdFile() htpasswdPath := MakeHtpasswdFile()
defer os.Remove(htpasswdPath) defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{ conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{ HTPasswd: config.AuthHTPasswd{
@ -157,7 +81,7 @@ func TestAuditLogMessages(t *testing.T) {
// wait till ready // wait till ready
for { for {
_, err := resty.R().Get(BaseURL) _, err := resty.R().Get(baseURL)
if err == nil { if err == nil {
break break
} }
@ -178,8 +102,7 @@ func TestAuditLogMessages(t *testing.T) {
defer auditFile.Close() defer auditFile.Close()
Convey("Test GET request", func() { Convey("Test GET request", func() {
resp, err := resty.R().SetBasicAuth(username, passphrase). resp, err := resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/")
Get(BaseURL + "/v2/")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK) So(resp.StatusCode(), ShouldEqual, http.StatusOK)
@ -190,8 +113,7 @@ func TestAuditLogMessages(t *testing.T) {
Convey("Test POST request", func() { Convey("Test POST request", func() {
path := "/v2/" + AuthorizedNamespace + "/blobs/uploads/" path := "/v2/" + AuthorizedNamespace + "/blobs/uploads/"
resp, err := resty.R().SetBasicAuth(username, passphrase). resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path)
Post(BaseURL + path)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
@ -221,10 +143,10 @@ func TestAuditLogMessages(t *testing.T) {
Convey("Test PUT and DELETE request", func() { Convey("Test PUT and DELETE request", func() {
// create upload // create upload
path := "/v2/repo/blobs/uploads/" path := "/v2/repo/blobs/uploads/"
resp, err := resty.R().SetBasicAuth(username, passphrase).Post(BaseURL + path) resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
loc := Location(BaseURL, resp) loc := Location(baseURL, resp)
So(loc, ShouldNotBeEmpty) So(loc, ShouldNotBeEmpty)
location := resp.Header().Get("Location") location := resp.Header().Get("Location")
So(location, ShouldNotBeEmpty) So(location, ShouldNotBeEmpty)
@ -260,7 +182,7 @@ func TestAuditLogMessages(t *testing.T) {
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(loc) SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(loc)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated) So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
blobLoc := Location(BaseURL, resp) blobLoc := Location(baseURL, resp)
So(blobLoc, ShouldNotBeEmpty) So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty) So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
@ -317,10 +239,10 @@ func TestAuditLogMessages(t *testing.T) {
Convey("Test PATCH request", func() { Convey("Test PATCH request", func() {
path := "/v2/repo/blobs/uploads/" path := "/v2/repo/blobs/uploads/"
resp, err := resty.R().SetBasicAuth(username, passphrase).Post(BaseURL + path) resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
loc := Location(BaseURL, resp) loc := Location(baseURL, resp)
So(loc, ShouldNotBeEmpty) So(loc, ShouldNotBeEmpty)
location := resp.Header().Get("Location") location := resp.Header().Get("Location")
So(location, ShouldNotBeEmpty) So(location, ShouldNotBeEmpty)

View file

@ -62,16 +62,7 @@ func (is *ImageStoreFS) RootDir() string {
} }
func (is *ImageStoreFS) DirExists(d string) bool { func (is *ImageStoreFS) DirExists(d string) bool {
fi, err := os.Stat(d) return DirExists(d)
if err != nil && os.IsNotExist(err) {
return false
}
if !fi.IsDir() {
return false
}
return true
} }
func getRoutePrefix(name string) string { func getRoutePrefix(name string) string {
@ -1341,3 +1332,16 @@ func ifOlderThan(is *ImageStoreFS, repo string, delay time.Duration) casext.GCPo
return true, nil return true, nil
} }
} }
func DirExists(d string) bool {
fi, err := os.Stat(d)
if err != nil && os.IsNotExist(err) {
return false
}
if !fi.IsDir() {
return false
}
return true
}

View file

@ -595,7 +595,7 @@ func TestNegativeCases(t *testing.T) {
So(err, ShouldNotBeNil) So(err, ShouldNotBeNil)
}) })
Convey("Invalid dedupe sceanrios", t, func() { Convey("Invalid dedupe scenarios", t, func() {
dir, err := ioutil.TempDir("", "oci-repo-test") dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil { if err != nil {
panic(err) panic(err)
@ -671,6 +671,23 @@ func TestNegativeCases(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(b, ShouldEqual, l) So(b, ShouldEqual, l)
}) })
Convey("DirExists call with a filename as argument", t, func(c C) {
dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
filePath := path.Join(dir, "file.txt")
err = ioutil.WriteFile(filePath, []byte("some dummy file content"), 0644) //nolint: gosec
if err != nil {
panic(err)
}
ok := storage.DirExists(filePath)
So(ok, ShouldBeFalse)
})
} }
func TestHardLink(t *testing.T) { func TestHardLink(t *testing.T) {

View file

@ -475,6 +475,15 @@ func TestStorageAPIs(t *testing.T) {
indexContent, err := il.GetIndexContent("test") indexContent, err := il.GetIndexContent("test")
So(err, ShouldBeNil) So(err, ShouldBeNil)
if testcase.storageType == "fs" {
err = os.Chmod(path.Join(il.RootDir(), "test", "index.json"), 0000)
So(err, ShouldBeNil)
_, err = il.GetIndexContent("test")
So(err, ShouldNotBeNil)
err = os.Chmod(path.Join(il.RootDir(), "test", "index.json"), 0644)
So(err, ShouldBeNil)
}
var index ispec.Index var index ispec.Index
err = json.Unmarshal(indexContent, &index) err = json.Unmarshal(indexContent, &index)

110
test/common.go Normal file
View file

@ -0,0 +1,110 @@
package test
import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
"github.com/phayes/freeport"
"gopkg.in/resty.v1"
)
const (
BaseURL = "http://127.0.0.1:%s"
BaseSecureURL = "https://127.0.0.1:%s"
)
func GetFreePort() string {
port, err := freeport.GetFreePort()
if err != nil {
panic(err)
}
return fmt.Sprint(port)
}
func GetBaseURL(port string) string {
return fmt.Sprintf(BaseURL, port)
}
func GetSecureBaseURL(port string) string {
return fmt.Sprintf(BaseSecureURL, port)
}
func MakeHtpasswdFile() string {
// bcrypt(username="test", passwd="test")
content := "test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n"
return MakeHtpasswdFileFromString(content)
}
func MakeHtpasswdFileFromString(fileContent string) string {
f, err := ioutil.TempFile("", "htpasswd-")
if err != nil {
panic(err)
}
// bcrypt(username="test", passwd="test")
content := []byte(fileContent)
if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil {
panic(err)
}
return f.Name()
}
func Location(baseURL string, resp *resty.Response) string {
// For some API responses, the Location header is set and is supposed to
// indicate an opaque value. However, it is not clear if this value is an
// absolute URL (https://server:port/v2/...) or just a path (/v2/...)
// zot implements the latter as per the spec, but some registries appear to
// return the former - this needs to be clarified
loc := resp.Header().Get("Location")
return baseURL + loc
}
func CopyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = CopyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}

81
test/common_test.go Normal file
View file

@ -0,0 +1,81 @@
// +build extended
package test_test
import (
"io/ioutil"
"os"
"path"
"testing"
. "github.com/anuvu/zot/test"
. "github.com/smartystreets/goconvey/convey"
)
func TestCopyFiles(t *testing.T) {
Convey("sourceDir does not exist", t, func() {
err := CopyFiles("/path/to/some/unexisting/directory", os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("destDir is a file", t, func() {
dir, err := ioutil.TempDir("", "copy-files-test")
if err != nil {
panic(err)
}
err = CopyFiles("data", dir)
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
err = CopyFiles(dir, "/etc/passwd")
So(err, ShouldNotBeNil)
})
Convey("sourceDir does not have read permissions", t, func() {
dir, err := ioutil.TempDir("", "copy-files-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
err = os.Chmod(dir, 0300)
So(err, ShouldBeNil)
err = CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("sourceDir has a subfolder that does not have read permissions", t, func() {
dir, err := ioutil.TempDir("", "copy-files-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
sdir := "subdir"
err = os.Mkdir(path.Join(dir, sdir), 0300)
So(err, ShouldBeNil)
err = CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("sourceDir has a file that does not have read permissions", t, func() {
dir, err := ioutil.TempDir("", "copy-files-test")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
filePath := path.Join(dir, "file.txt")
err = ioutil.WriteFile(filePath, []byte("some dummy file content"), 0644) //nolint: gosec
if err != nil {
panic(err)
}
err = os.Chmod(filePath, 0300)
So(err, ShouldBeNil)
err = CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
}