From 6c293719e3a74edbfa605a2acfda13f39b45943b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 10 Aug 2022 22:28:52 +0000 Subject: [PATCH] storage: different subpaths can point to same root directory currently different subpaths can only point to same root directory only when one or both of the storage config does not enable dedupe different subpath should be able to point to same root directory and in that case their storage config should be same i.e GC,Dedupe, GC delay and GC interval Signed-off-by: Shivam Mishra --- pkg/api/config/config.go | 22 ++++ pkg/api/config/config_elevated_test.go | 32 ++++++ pkg/api/config/config_test.go | 67 ++++++++++++ pkg/api/controller.go | 146 +++++++++++++++++-------- pkg/api/controller_test.go | 64 +++++++++++ pkg/cli/root.go | 33 ++++++ pkg/cli/root_test.go | 121 ++++++++++++++++++++ pkg/extensions/sync/sync_test.go | 6 +- 8 files changed, 441 insertions(+), 50 deletions(-) create mode 100644 pkg/api/config/config_elevated_test.go create mode 100644 pkg/api/config/config_test.go diff --git a/pkg/api/config/config.go b/pkg/api/config/config.go index 76ada3f0..79b5ad87 100644 --- a/pkg/api/config/config.go +++ b/pkg/api/config/config.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "os" "time" "github.com/getlantern/deepcopy" @@ -144,6 +145,27 @@ func New() *Config { } } +func (expConfig StorageConfig) ParamsEqual(actConfig StorageConfig) bool { + return expConfig.GC == actConfig.GC && expConfig.Dedupe == actConfig.Dedupe && + expConfig.GCDelay == actConfig.GCDelay && expConfig.GCInterval == actConfig.GCInterval +} + +// SameFile compare two files. +// This method will first do the stat of two file and compare using os.SameFile method. +func SameFile(str1, str2 string) (bool, error) { + sFile, err := os.Stat(str1) + if err != nil { + return false, err + } + + tFile, err := os.Stat(str2) + if err != nil { + return false, err + } + + return os.SameFile(sFile, tFile), nil +} + // Sanitize makes a sanitized copy of the config removing any secrets. func (c *Config) Sanitize() *Config { sanitizedConfig := &Config{} diff --git a/pkg/api/config/config_elevated_test.go b/pkg/api/config/config_elevated_test.go new file mode 100644 index 00000000..3b1a0b0c --- /dev/null +++ b/pkg/api/config/config_elevated_test.go @@ -0,0 +1,32 @@ +//go:build needprivileges +// +build needprivileges + +package config_test + +import ( + "syscall" + "testing" + + . "github.com/smartystreets/goconvey/convey" + + "zotregistry.io/zot/pkg/api/config" +) + +func TestMountConfig(t *testing.T) { + Convey("Test config utils mounting same directory", t, func() { + // If two dirs are mounting to same location SameFile should be same + dir1 := t.TempDir() + dir2 := t.TempDir() + dir3 := t.TempDir() + + err := syscall.Mount(dir3, dir1, "", syscall.MS_BIND, "") + So(err, ShouldBeNil) + + err = syscall.Mount(dir3, dir2, "", syscall.MS_BIND, "") + So(err, ShouldBeNil) + + isSame, err := config.SameFile(dir1, dir2) + So(err, ShouldBeNil) + So(isSame, ShouldBeTrue) + }) +} diff --git a/pkg/api/config/config_test.go b/pkg/api/config/config_test.go new file mode 100644 index 00000000..85611e0d --- /dev/null +++ b/pkg/api/config/config_test.go @@ -0,0 +1,67 @@ +package config_test + +import ( + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" + "zotregistry.io/zot/pkg/api/config" +) + +func TestConfig(t *testing.T) { + Convey("Test config utils", t, func() { + firstStorageConfig := config.StorageConfig{ + GC: true, Dedupe: true, + GCDelay: 1 * time.Minute, GCInterval: 1 * time.Hour, + } + secondStorageConfig := config.StorageConfig{ + GC: true, Dedupe: true, + GCDelay: 1 * time.Minute, GCInterval: 1 * time.Hour, + } + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeTrue) + + firstStorageConfig.GC = false + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeFalse) + + firstStorageConfig.GC = true + firstStorageConfig.Dedupe = false + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeFalse) + + firstStorageConfig.Dedupe = true + firstStorageConfig.GCDelay = 2 * time.Minute + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeFalse) + + firstStorageConfig.GCDelay = 1 * time.Minute + firstStorageConfig.GCInterval = 2 * time.Hour + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeFalse) + + firstStorageConfig.GCInterval = 1 * time.Hour + + So(firstStorageConfig.ParamsEqual(secondStorageConfig), ShouldBeTrue) + + isSame, err := config.SameFile("test-config", "test") + So(err, ShouldNotBeNil) + So(isSame, ShouldBeFalse) + + dir1 := t.TempDir() + + isSame, err = config.SameFile(dir1, "test") + So(err, ShouldNotBeNil) + So(isSame, ShouldBeFalse) + + dir2 := t.TempDir() + + isSame, err = config.SameFile(dir1, dir2) + So(err, ShouldBeNil) + So(isSame, ShouldBeFalse) + + isSame, err = config.SameFile(dir1, dir1) + So(err, ShouldBeNil) + So(isSame, ShouldBeTrue) + }) +} diff --git a/pkg/api/controller.go b/pkg/api/controller.go index b9f747bd..bf2eff32 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -21,6 +21,7 @@ import ( "zotregistry.io/zot/pkg/api/config" ext "zotregistry.io/zot/pkg/extensions" extconf "zotregistry.io/zot/pkg/extensions/config" + "zotregistry.io/zot/pkg/extensions/lint" "zotregistry.io/zot/pkg/extensions/monitoring" "zotregistry.io/zot/pkg/log" "zotregistry.io/zot/pkg/storage" @@ -281,54 +282,11 @@ func (c *Controller) InitImageStore(reloadCtx context.Context) error { if len(c.Config.Storage.SubPaths) > 0 { subPaths := c.Config.Storage.SubPaths - subImageStore := make(map[string]storage.ImageStore) + subImageStore, err := c.getSubStore(subPaths, linter) + if err != nil { + c.Log.Error().Err(err).Msg("controller: error getting sub image store") - // creating image store per subpaths - for route, storageConfig := range subPaths { - // no need to validate hard links work on s3 - if storageConfig.Dedupe && storageConfig.StorageDriver == nil { - err := storage.ValidateHardLink(storageConfig.RootDirectory) - if err != nil { - c.Log.Warn().Msg("input storage root directory filesystem does not supports hardlinking, " + - "disabling dedupe functionality") - - storageConfig.Dedupe = false - } - } - - if storageConfig.StorageDriver == nil { - // false positive lint - linter does not implement Lint method - // nolint: typecheck - subImageStore[route] = storage.NewImageStore(storageConfig.RootDirectory, - storageConfig.GC, storageConfig.GCDelay, storageConfig.Dedupe, storageConfig.Commit, c.Log, c.Metrics, linter) - } else { - storeName := fmt.Sprintf("%v", storageConfig.StorageDriver["name"]) - if storeName != storage.S3StorageDriverName { - c.Log.Fatal().Err(errors.ErrBadConfig).Msgf("unsupported storage driver: %s", storageConfig.StorageDriver["name"]) - } - - // Init a Storager from connection string. - store, err := factory.Create(storeName, storageConfig.StorageDriver) - if err != nil { - c.Log.Error().Err(err).Str("rootDir", storageConfig.RootDirectory).Msg("Unable to create s3 service") - - return err - } - - /* in the case of s3 c.Config.Storage.RootDirectory is used for caching blobs locally and - c.Config.Storage.StorageDriver["rootdirectory"] is the actual rootDir in s3 */ - rootDir := "/" - if c.Config.Storage.StorageDriver["rootdirectory"] != nil { - rootDir = fmt.Sprintf("%v", c.Config.Storage.StorageDriver["rootdirectory"]) - } - - // false positive lint - linter does not implement Lint method - // nolint: typecheck - subImageStore[route] = s3.NewImageStore(rootDir, storageConfig.RootDirectory, - storageConfig.GC, storageConfig.GCDelay, - storageConfig.Dedupe, storageConfig.Commit, c.Log, c.Metrics, linter, store, - ) - } + return err } c.StoreController.SubStore = subImageStore @@ -340,6 +298,100 @@ func (c *Controller) InitImageStore(reloadCtx context.Context) error { return nil } +func (c *Controller) getSubStore(subPaths map[string]config.StorageConfig, + linter *lint.Linter, +) (map[string]storage.ImageStore, error) { + imgStoreMap := make(map[string]storage.ImageStore, 0) + + subImageStore := make(map[string]storage.ImageStore) + + // creating image store per subpaths + for route, storageConfig := range subPaths { + // no need to validate hard links work on s3 + if storageConfig.Dedupe && storageConfig.StorageDriver == nil { + err := storage.ValidateHardLink(storageConfig.RootDirectory) + if err != nil { + c.Log.Warn().Msg("input storage root directory filesystem does not supports hardlinking, " + + "disabling dedupe functionality") + + storageConfig.Dedupe = false + } + } + + if storageConfig.StorageDriver == nil { + // Compare if subpath root dir is same as default root dir + isSame, _ := config.SameFile(c.Config.Storage.RootDirectory, storageConfig.RootDirectory) + + if isSame { + c.Log.Error().Err(errors.ErrBadConfig).Msg("sub path storage directory is same as root directory") + + return nil, errors.ErrBadConfig + } + + isUnique := true + + // Compare subpath unique files + for file := range imgStoreMap { + // We already have image storage for this file + if compareImageStore(file, storageConfig.RootDirectory) { + subImageStore[route] = imgStoreMap[file] + + isUnique = true + } + } + + // subpath root directory is unique + // add it to uniqueSubFiles + // Create a new image store and assign it to imgStoreMap + if isUnique { + imgStoreMap[storageConfig.RootDirectory] = storage.NewImageStore(storageConfig.RootDirectory, + storageConfig.GC, storageConfig.GCDelay, storageConfig.Dedupe, storageConfig.Commit, c.Log, c.Metrics, linter) + + subImageStore[route] = imgStoreMap[storageConfig.RootDirectory] + } + } else { + storeName := fmt.Sprintf("%v", storageConfig.StorageDriver["name"]) + if storeName != storage.S3StorageDriverName { + c.Log.Fatal().Err(errors.ErrBadConfig).Msgf("unsupported storage driver: %s", storageConfig.StorageDriver["name"]) + } + + // Init a Storager from connection string. + store, err := factory.Create(storeName, storageConfig.StorageDriver) + if err != nil { + c.Log.Error().Err(err).Str("rootDir", storageConfig.RootDirectory).Msg("Unable to create s3 service") + + return nil, err + } + + /* in the case of s3 c.Config.Storage.RootDirectory is used for caching blobs locally and + c.Config.Storage.StorageDriver["rootdirectory"] is the actual rootDir in s3 */ + rootDir := "/" + if c.Config.Storage.StorageDriver["rootdirectory"] != nil { + rootDir = fmt.Sprintf("%v", c.Config.Storage.StorageDriver["rootdirectory"]) + } + + // false positive lint - linter does not implement Lint method + // nolint: typecheck + subImageStore[route] = s3.NewImageStore(rootDir, storageConfig.RootDirectory, + storageConfig.GC, storageConfig.GCDelay, + storageConfig.Dedupe, storageConfig.Commit, c.Log, c.Metrics, linter, store, + ) + } + } + + return subImageStore, nil +} + +func compareImageStore(root1, root2 string) bool { + isSameFile, err := config.SameFile(root1, root2) + // This error is path error that means either of root directory doesn't exist, in that case do string match + if err != nil { + return strings.EqualFold(root1, root2) + } + + return isSameFile +} + func (c *Controller) LoadNewConfig(reloadCtx context.Context, config *config.Config) { // reload access control config c.Config.AccessControl = config.AccessControl diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index 91e3d799..9e634a29 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -839,6 +839,70 @@ func TestMultipleInstance(t *testing.T) { So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) + + Convey("Test zot multiple subpath with same root directory", t, func() { + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + htpasswdPath := test.MakeHtpasswdFile() + defer os.Remove(htpasswdPath) + + conf.HTTP.Auth = &config.AuthConfig{ + HTPasswd: config.AuthHTPasswd{ + Path: htpasswdPath, + }, + } + ctlr := api.NewController(conf) + globalDir := t.TempDir() + subDir := t.TempDir() + + ctlr.Config.Storage.RootDirectory = globalDir + subPathMap := make(map[string]config.StorageConfig) + subPathMap["/a"] = config.StorageConfig{RootDirectory: globalDir, Dedupe: true, GC: true} + subPathMap["/b"] = config.StorageConfig{RootDirectory: subDir, Dedupe: true, GC: true} + + ctlr.Config.Storage.SubPaths = subPathMap + + err := ctlr.Run(context.Background()) + So(err, ShouldNotBeNil) + + // subpath root directory does not exist. + subPathMap["/a"] = config.StorageConfig{RootDirectory: globalDir, Dedupe: true, GC: true} + subPathMap["/b"] = config.StorageConfig{RootDirectory: subDir, Dedupe: false, GC: true} + + ctlr.Config.Storage.SubPaths = subPathMap + + err = ctlr.Run(context.Background()) + So(err, ShouldNotBeNil) + + subPathMap["/a"] = config.StorageConfig{RootDirectory: subDir, Dedupe: true, GC: true} + subPathMap["/b"] = config.StorageConfig{RootDirectory: subDir, Dedupe: true, GC: true} + + ctlr.Config.Storage.SubPaths = subPathMap + + go startServer(ctlr) + defer stopServer(ctlr) + test.WaitTillServerReady(baseURL) + + // without creds, should get access error + resp, err := resty.R().Get(baseURL + "/v2/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e api.Error + err = json.Unmarshal(resp.Body(), &e) + So(err, ShouldBeNil) + + // with creds, should get expected status code + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) } func TestTLSWithBasicAuth(t *testing.T) { diff --git a/pkg/cli/root.go b/pkg/cli/root.go index 7b0891f0..19f8948c 100644 --- a/pkg/cli/root.go +++ b/pkg/cli/root.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/http" + "strings" "time" glob "github.com/bmatcuk/doublestar/v4" @@ -202,6 +203,34 @@ func NewCliRootCmd() *cobra.Command { return rootCmd } +func validateStorageConfig(cfg *config.Config) error { + expConfigMap := make(map[string]config.StorageConfig, 0) + + defaultRootDir := cfg.Storage.RootDirectory + + for _, storageConfig := range cfg.Storage.SubPaths { + if strings.EqualFold(defaultRootDir, storageConfig.RootDirectory) { + log.Error().Err(errors.ErrBadConfig).Msg("storage subpaths cannot use default storage root directory") + + return errors.ErrBadConfig + } + + expConfig, ok := expConfigMap[storageConfig.RootDirectory] + if ok { + equal := expConfig.ParamsEqual(storageConfig) + if !equal { + log.Error().Err(errors.ErrBadConfig).Msg("storage config with same root directory should have same parameters") + + return errors.ErrBadConfig + } + } else { + expConfigMap[storageConfig.RootDirectory] = storageConfig + } + } + + return nil +} + func validateConfiguration(config *config.Config) error { if err := validateGC(config); err != nil { return err @@ -215,6 +244,10 @@ func validateConfiguration(config *config.Config) error { return err } + if err := validateStorageConfig(config); err != nil { + return err + } + // check authorization config, it should have basic auth enabled or ldap if config.HTTP.RawAccessControl != nil { // checking for anonymous policy only authorization config: no users, no policies but anonymous policy diff --git a/pkg/cli/root_test.go b/pkg/cli/root_test.go index 24e4db6b..5d20b779 100644 --- a/pkg/cli/root_test.go +++ b/pkg/cli/root_test.go @@ -141,6 +141,82 @@ func TestVerify(t *testing.T) { So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) }) + Convey("Test verify subpath storage config", t, func(c C) { + tmpfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a"},"/b": {"rootDirectory": "/zot-a"}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + + // sub paths that point to same directory should have same storage config. + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true"}, + "/b": {{"rootDirectory": "/zot-a","dedupe":"false"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + + // sub paths that point to default root directory should not be allowed. + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/tmp/zot","dedupe":"true"},"/b": {{"rootDirectory": "/zot-a"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"false"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s","gcInterval":"1s"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/tmp/zot","dedupe":"true","gc":"true","gcDelay":"1s","gcInterval":"1s"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic) + }) + Convey("Test verify w/ authorization and w/o authentication", t, func(c C) { tmpfile, err := ioutil.TempFile("", "zot-test*.json") So(err, ShouldBeNil) @@ -420,6 +496,51 @@ func TestLoadConfig(t *testing.T) { err := cli.LoadConfiguration(config, "../../examples/config-policy.json") So(err, ShouldBeNil) }) + Convey("Test subpath config combination", t, func(c C) { + config := config.New() + tmpfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/tmp/zot","dedupe":"true","gc":"true","gcDelay":"1s","gcInterval":"1s"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + err = cli.LoadConfiguration(config, tmpfile.Name()) + So(err, ShouldNotBeNil) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s","gcInterval":"1s"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + err = cli.LoadConfiguration(config, tmpfile.Name()) + So(err, ShouldNotBeNil) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"false"}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + err = cli.LoadConfiguration(config, tmpfile.Name()) + So(err, ShouldNotBeNil) + + content = []byte(`{"storage":{"rootDirectory":"/tmp/zot", + "subPaths": {"/a": {"rootDirectory": "/zot-a","dedupe":"true"}, + "/b": {"rootDirectory": "/zot-a","dedupe":"true"}}}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot", + "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) + err = os.WriteFile(tmpfile.Name(), content, 0o0600) + So(err, ShouldBeNil) + err = cli.LoadConfiguration(config, tmpfile.Name()) + So(err, ShouldBeNil) + }) } func TestGC(t *testing.T) { diff --git a/pkg/extensions/sync/sync_test.go b/pkg/extensions/sync/sync_test.go index dfdd3c67..be9dcf28 100644 --- a/pkg/extensions/sync/sync_test.go +++ b/pkg/extensions/sync/sync_test.go @@ -286,8 +286,6 @@ func TestORAS(t *testing.T) { panic(err) } - fmt.Println(fileDir) - srcURL := strings.Join([]string{sctlr.Server.Addr, "/oras-artifact:v2"}, "") cmd = exec.Command("oras", "push", "--plain-http", srcURL, "--config", @@ -1220,7 +1218,9 @@ func TestBasicAuth(t *testing.T) { }, } - destConfig.Storage.RootDirectory = destDir + rootDir := t.TempDir() + + destConfig.Storage.RootDirectory = rootDir regex := ".*" var semver bool