From 47c9b6244ef492b876fa9d45f6352c96ce760cb9 Mon Sep 17 00:00:00 2001 From: Alexei Dodon Date: Tue, 28 Dec 2021 15:29:30 +0200 Subject: [PATCH] Added config enable=true/false for extensions with default value as enabled closes #258 Signed-off-by: Alexei Dodon --- .gitignore | 4 +- examples/README.md | 10 +- examples/config-allextensions.json | 46 ++ examples/config-sync.json | 1 + pkg/api/controller.go | 5 +- pkg/api/routes.go | 8 +- pkg/cli/cve_cmd_test.go | 10 +- pkg/cli/extensions_test.go | 666 +++++++++++++++++++ pkg/cli/image_cmd_test.go | 3 +- pkg/cli/root.go | 74 ++- pkg/exporter/api/controller_test.go | 16 +- pkg/extensions/config/config.go | 4 +- pkg/extensions/extensions.go | 12 +- pkg/extensions/monitoring/monitoring_test.go | 6 +- pkg/extensions/search/common/common_test.go | 3 +- pkg/extensions/search/cve/cve_test.go | 13 +- pkg/extensions/search/digest/digest_test.go | 9 +- pkg/extensions/sync/sync.go | 1 + pkg/extensions/sync/sync_test.go | 164 ++++- 19 files changed, 970 insertions(+), 85 deletions(-) create mode 100644 examples/config-allextensions.json create mode 100644 pkg/cli/extensions_test.go diff --git a/.gitignore b/.gitignore index 8bc5c131..96dadea9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,9 +13,7 @@ bin/ bazel-* -coverage.txt -coverage-extended.txt -coverage-minimal.txt +coverage*.txt test/data/ *.orig .idea/ diff --git a/examples/README.md b/examples/README.md index 03ca0cee..f9dc841c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -388,7 +388,7 @@ Configure each registry sync: "pollInterval": "6h", # polling interval, if not set then periodically polling will not run "tlsVerify": true, # whether or not to verify tls (default is true) "certDir": "/home/user/certs", # use certificates at certDir path, if not specified then use the default certs dir - "maxRetries": 5, # mandatory option! maxRetries in case of temporary errors + "maxRetries": 5, # mandatory option! maxRetries in case of temporary errors "retryDelay": "10m", # mandatory option! delay between retries, retry options are applied for both on demand and periodically sync. "content":[ # which content to periodically pull, also it's used for filtering ondemand images, if not set then periodically polling will not run { @@ -401,7 +401,7 @@ Configure each registry sync: { "prefix":"/repo2/repo*" # pull all images that matches repo2/repo.* }, - { + { "prefix":"/repo3/**" # pull all images under repo3/ (matches recursively all repos under repo3/) } ] @@ -411,7 +411,7 @@ Configure each registry sync: "pollInterval": "12h", "tlsVerify": false, "onDemand": false, - "maxRetries": 5, + "maxRetries": 5, "retryDelay": "10m", "content":[ { @@ -426,8 +426,8 @@ Configure each registry sync: "urls": ["https://docker.io/library"], "onDemand": true, # doesn't have content, don't periodically pull, pull just on demand. "tlsVerify": true, - "maxRetries": 3, - "retryDelay": "15m" + "maxRetries": 3, + "retryDelay": "15m" } ] } diff --git a/examples/config-allextensions.json b/examples/config-allextensions.json new file mode 100644 index 00000000..b811ace1 --- /dev/null +++ b/examples/config-allextensions.json @@ -0,0 +1,46 @@ +{ + "version": "0.1.0-dev", + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "8080" + }, + "log": { + "level": "debug" + }, + "extensions": { + "metrics": { + }, + "sync": { + "credentialsFile": "./examples/sync-auth-filepath.json", + "registries": [{ + "urls": ["https://registry1:5000"], + "onDemand": false, + "pollInterval": "6h", + "tlsVerify": true, + "certDir": "/home/user/certs", + "maxRetries": 3, + "retryDelay": "15m", + "content":[ + { + "prefix":"/repo1/repo", + "tags":{ + "regex":"4.*", + "semver":true + } + }, + { + "prefix":"/repo2/repo" + } + ] + }] + }, + "search": { + "cve": { + "updateInterval": "2h" + } + } + } +} diff --git a/examples/config-sync.json b/examples/config-sync.json index cdc6360e..9cd847ce 100644 --- a/examples/config-sync.json +++ b/examples/config-sync.json @@ -12,6 +12,7 @@ }, "extensions":{ "sync": { + "enable": true, "credentialsFile": "./examples/sync-auth-filepath.json", "registries": [{ "urls": ["https://registry1:5000"], diff --git a/pkg/api/controller.go b/pkg/api/controller.go index 8c22f5f4..5bec00fe 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -45,7 +45,6 @@ func NewController(config *config.Config) *Controller { var controller Controller logger := log.NewLogger(config.Log.Level, config.Log.Output) - controller.Config = config controller.Log = logger controller.wgShutDown = new(goSync.WaitGroup) @@ -137,7 +136,7 @@ func (c *Controller) Run() error { if c.Config != nil && c.Config.Extensions != nil && c.Config.Extensions.Metrics != nil && - c.Config.Extensions.Metrics.Enable { + *c.Config.Extensions.Metrics.Enable { enabled = true } @@ -296,7 +295,7 @@ func (c *Controller) InitImageStore() error { } // Enable extensions if extension config is provided - if c.Config.Extensions != nil && c.Config.Extensions.Sync != nil { + if c.Config.Extensions != nil && c.Config.Extensions.Sync != nil && *c.Config.Extensions.Sync.Enable { ext.EnableSyncExtension(c.Config, c.wgShutDown, c.StoreController, c.Log) } diff --git a/pkg/api/routes.go b/pkg/api/routes.go index f9e03aba..9dcdd5a2 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -1324,7 +1324,9 @@ func getImageManifest(routeHandler *RouteHandler, imgStore storage.ImageStore, n content, digest, mediaType, err := imgStore.GetImageManifest(name, reference) if err != nil { if errors.Is(err, zerr.ErrRepoNotFound) || errors.Is(err, zerr.ErrManifestNotFound) { - if routeHandler.c.Config.Extensions != nil && routeHandler.c.Config.Extensions.Sync != nil { + if routeHandler.c.Config.Extensions != nil && + routeHandler.c.Config.Extensions.Sync != nil && + *routeHandler.c.Config.Extensions.Sync.Enable { routeHandler.c.Log.Info().Msgf("image not found, trying to get image %s:%s by syncing on demand", name, reference) @@ -1350,7 +1352,9 @@ func getReferrers(routeHandler *RouteHandler, imgStore storage.ImageStore, name, artifactType string) ([]artifactspec.Descriptor, error) { refs, err := imgStore.GetReferrers(name, digest, artifactType) if err != nil { - if routeHandler.c.Config.Extensions != nil && routeHandler.c.Config.Extensions.Sync != nil { + if routeHandler.c.Config.Extensions != nil && + routeHandler.c.Config.Extensions.Sync != nil && + *routeHandler.c.Config.Extensions.Sync.Enable { routeHandler.c.Log.Info().Msgf("signature not found, trying to get signature %s:%s by syncing on demand", name, digest) diff --git a/pkg/cli/cve_cmd_test.go b/pkg/cli/cve_cmd_test.go index f3bb655b..9040c6d4 100644 --- a/pkg/cli/cve_cmd_test.go +++ b/pkg/cli/cve_cmd_test.go @@ -290,7 +290,6 @@ func TestServerCVEResponse(t *testing.T) { url := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port - ctlr := api.NewController(conf) dir, err := ioutil.TempDir("", "oci-repo-test") if err != nil { @@ -304,18 +303,21 @@ func TestServerCVEResponse(t *testing.T) { defer os.RemoveAll(dir) - ctlr.Config.Storage.RootDirectory = dir + conf.Storage.RootDirectory = dir cveConfig := &extconf.CVEConfig{ UpdateInterval: 2, } + defaultVal := true searchConfig := &extconf.SearchConfig{ CVE: cveConfig, - Enable: true, + Enable: &defaultVal, } - ctlr.Config.Extensions = &extconf.ExtensionConfig{ + conf.Extensions = &extconf.ExtensionConfig{ Search: searchConfig, } + ctlr := api.NewController(conf) + go func(controller *api.Controller) { // this blocks if err := controller.Run(); err != nil { diff --git a/pkg/cli/extensions_test.go b/pkg/cli/extensions_test.go new file mode 100644 index 00000000..a8836ac1 --- /dev/null +++ b/pkg/cli/extensions_test.go @@ -0,0 +1,666 @@ +//go:build extended +// +build extended + +package cli_test + +import ( + "fmt" + "io/ioutil" + "net/http" + "os" + "testing" + + . "github.com/smartystreets/goconvey/convey" + "gopkg.in/resty.v1" + "zotregistry.io/zot/pkg/cli" + . "zotregistry.io/zot/pkg/test" +) + +func TestServeExtensions(t *testing.T) { + oldArgs := os.Args + + defer func() { os.Args = oldArgs }() + + Convey("config file with no extensions", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + + WaitTillServerReady(baseURL) + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, "\"Extensions\":null") + }) + + Convey("config file with empty extensions", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + + WaitTillServerReady(baseURL) + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":null") + }) +} + +func testWithMetricsEnabled(cfgContentFormat string) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(cfgContentFormat, port, logFile.Name()) + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + respStr := string(resp.Body()) + So(respStr, ShouldContainSubstring, "zot_info") + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":{\"Enable\":true,\"Prometheus\":{\"Path\":\"/metrics\"}}}") // nolint:lll +} + +func TestServeMetricsExtension(t *testing.T) { + oldArgs := os.Args + + defer func() { os.Args = oldArgs }() + + Convey("no explicit enable", t, func(c C) { + content := `{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "metrics": { + } + } + }` + testWithMetricsEnabled(content) + }) + + Convey("no explicit enable but with prometheus parameter", t, func(c C) { + content := `{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "metrics": { + "prometheus": { + "path": "/metrics" + } + } + } + }` + testWithMetricsEnabled(content) + }) + + Convey("with explicit enable, but without prometheus parameter", t, func(c C) { + content := `{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "metrics": { + "enable": true + } + } + }` + testWithMetricsEnabled(content) + }) + + Convey("with explicit disable", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "metrics": { + "enable": false + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":{\"Enable\":false,\"Prometheus\":{\"Path\":\"/metrics\"}}}") // nolint:lll + }) +} + +func TestServeSyncExtension(t *testing.T) { + oldArgs := os.Args + + defer func() { os.Args = oldArgs }() + + Convey("sync implicitly enabled", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "sync": { + "registries": [{ + "urls": ["http://localhost:8080"], + "tlsVerify": false, + "onDemand": true, + "maxRetries": 3, + "retryDelay": "15m", + "certDir": "", + "content":[ + { + "prefix": "zot-test", + "tags": { + "regex": ".*", + "semver": true + } + } + ] + }] + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":true") + }) + + Convey("sync explicitly enabled", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "sync": { + "enable": true, + "registries": [{ + "urls": ["http://localhost:8080"], + "tlsVerify": false, + "onDemand": true, + "maxRetries": 3, + "retryDelay": "15m", + "certDir": "", + "content":[ + { + "prefix": "zot-test", + "tags": { + "regex": ".*", + "semver": true + } + } + ] + }] + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":true") + }) + + Convey("sync explicitly disabled", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "sync": { + "enable": false, + "registries": [{ + "urls": ["http://127.0.0.1:8080"], + "tlsVerify": false, + "certDir": "", + "maxRetries": 3, + "retryDelay": "15m" + }] + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":false") + }) +} + +func TestServeSearchExtension(t *testing.T) { + oldArgs := os.Args + + defer func() { os.Args = oldArgs }() + + Convey("search implicitly enabled", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "search": { + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":{\"CVE\":{\"UpdateInterval\":86400000000000},\"Enable\":true},\"Sync\":null,\"Metrics\":null}") // nolint:lll + So(string(data), ShouldContainSubstring, "updating the CVE database") + }) + + Convey("search implicitly enabled with CVE param set", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "search": { + "cve": { + "updateInterval": "1h" + } + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + // Even if in config we specified updateInterval=1h, the minimum interval is 2h + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":{\"CVE\":{\"UpdateInterval\":3600000000000},\"Enable\":true},\"Sync\":null,\"Metrics\":null}") // nolint:lll + So(string(data), ShouldContainSubstring, "updating the CVE database") + So(string(data), ShouldContainSubstring, + "CVE update interval set to too-short interval < 2h, changing update duration to 2 hours and continuing.") + }) + + Convey("search explicitly enabled, but CVE parameter not set", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "search": { + "enable": true + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":{\"CVE\":{\"UpdateInterval\":86400000000000},\"Enable\":true},\"Sync\":null,\"Metrics\":null}") // nolint:lll + So(string(data), ShouldContainSubstring, "updating the CVE database") + }) + + Convey("search explicitly disabled", t, func(c C) { + port := GetFreePort() + baseURL := GetBaseURL(port) + logFile, err := ioutil.TempFile("", "zot-log*.txt") + So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + + content := fmt.Sprintf(`{ + "storage": { + "rootDirectory": "/tmp/zot" + }, + "http": { + "address": "127.0.0.1", + "port": "%s" + }, + "log": { + "level": "debug", + "output": "%s" + }, + "extensions": { + "search": { + "enable": false, + "cve": { + "updateInterval": "3h" + } + } + } + }`, port, logFile.Name()) + + cfgfile, err := ioutil.TempFile("", "zot-test*.json") + So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.Write([]byte(content)) + So(err, ShouldBeNil) + err = cfgfile.Close() + So(err, ShouldBeNil) + + os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }() + WaitTillServerReady(baseURL) + + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) + So(string(data), ShouldContainSubstring, + "\"Extensions\":{\"Search\":{\"CVE\":{\"UpdateInterval\":10800000000000},\"Enable\":false},\"Sync\":null,\"Metrics\":null}") // nolint:lll + So(string(data), ShouldContainSubstring, "CVE config not provided, skipping CVE update") + So(string(data), ShouldNotContainSubstring, + "CVE update interval set to too-short interval < 2h, changing update duration to 2 hours and continuing.") + }) +} diff --git a/pkg/cli/image_cmd_test.go b/pkg/cli/image_cmd_test.go index 901a5005..a697f124 100644 --- a/pkg/cli/image_cmd_test.go +++ b/pkg/cli/image_cmd_test.go @@ -286,8 +286,9 @@ func TestServerResponse(t *testing.T) { url := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port + defaultVal := true conf.Extensions = &extconf.ExtensionConfig{ - Search: &extconf.SearchConfig{Enable: true}, + Search: &extconf.SearchConfig{Enable: &defaultVal}, } ctlr := api.NewController(conf) dir, err := ioutil.TempDir("", "oci-repo-test") diff --git a/pkg/cli/root.go b/pkg/cli/root.go index 223a6008..725dad5c 100644 --- a/pkg/cli/root.go +++ b/pkg/cli/root.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "time" glob "github.com/bmatcuk/doublestar/v4" "github.com/fsnotify/fsnotify" @@ -15,6 +16,7 @@ import ( "zotregistry.io/zot/errors" "zotregistry.io/zot/pkg/api" "zotregistry.io/zot/pkg/api/config" + extconf "zotregistry.io/zot/pkg/extensions/config" "zotregistry.io/zot/pkg/extensions/monitoring" "zotregistry.io/zot/pkg/storage" ) @@ -293,6 +295,64 @@ func validateConfiguration(config *config.Config) { } } +func applyDefaultValues(config *config.Config, viperInstance *viper.Viper) { + defaultVal := true + + if config.Extensions == nil && viperInstance.Get("extensions") != nil { + config.Extensions = &extconf.ExtensionConfig{} + + extMap := viperInstance.GetStringMap("extensions") + _, ok := extMap["metrics"] + + if ok { + // we found a config like `"extensions": {"metrics": {}}` + // Note: In case metrics is not empty the config.Extensions will not be nil and we will not reach here + config.Extensions.Metrics = &extconf.MetricsConfig{} + } + + _, ok = extMap["search"] + if ok { + // we found a config like `"extensions": {"search": {}}` + // Note: In case search is not empty the config.Extensions will not be nil and we will not reach here + config.Extensions.Search = &extconf.SearchConfig{} + } + } + + if config.Extensions != nil { + if config.Extensions.Sync != nil { + if config.Extensions.Sync.Enable == nil { + config.Extensions.Sync.Enable = &defaultVal + } + + for id, regCfg := range config.Extensions.Sync.Registries { + if regCfg.TLSVerify == nil { + config.Extensions.Sync.Registries[id].TLSVerify = &defaultVal + } + } + } + + if config.Extensions.Search != nil { + if config.Extensions.Search.Enable == nil { + config.Extensions.Search.Enable = &defaultVal + } + + if config.Extensions.Search.CVE == nil { + config.Extensions.Search.CVE = &extconf.CVEConfig{UpdateInterval: 24 * time.Hour} // nolint: gomnd + } + } + + if config.Extensions.Metrics != nil { + if config.Extensions.Metrics.Enable == nil { + config.Extensions.Metrics.Enable = &defaultVal + } + + if config.Extensions.Metrics.Prometheus == nil { + config.Extensions.Metrics.Prometheus = &extconf.PrometheusConfig{Path: "/metrics"} + } + } + } +} + func LoadConfiguration(config *config.Config, configPath string) { // Default is dot (.) but because we allow glob patterns in authz // we need another key delimiter. @@ -322,17 +382,9 @@ func LoadConfiguration(config *config.Config, configPath string) { panic(err) } + // defaults + applyDefaultValues(config, viperInstance) + // various config checks validateConfiguration(config) - - // defaults - defaultTLSVerify := true - - if config.Extensions != nil && config.Extensions.Sync != nil { - for id, regCfg := range config.Extensions.Sync.Registries { - if regCfg.TLSVerify == nil { - config.Extensions.Sync.Registries[id].TLSVerify = &defaultTLSVerify - } - } - } } diff --git a/pkg/exporter/api/controller_test.go b/pkg/exporter/api/controller_test.go index 58cffe44..aae4d44e 100644 --- a/pkg/exporter/api/controller_test.go +++ b/pkg/exporter/api/controller_test.go @@ -29,12 +29,8 @@ import ( . "zotregistry.io/zot/pkg/test" ) -const ( - SecondToNanoseconds = 1000000000 -) - -func getRandomLatencyN(maxNanoSeconds int64) time.Duration { - nBig, err := rand.Int(rand.Reader, big.NewInt(maxNanoSeconds)) +func getRandomLatencyN(max int64) time.Duration { + nBig, err := rand.Int(rand.Reader, big.NewInt(max)) if err != nil { panic(err) } @@ -43,7 +39,7 @@ func getRandomLatencyN(maxNanoSeconds int64) time.Duration { } func getRandomLatency() time.Duration { - return getRandomLatencyN(120 * SecondToNanoseconds) // a random latency (in nanoseconds) that can be up to 2 minutes + return getRandomLatencyN(int64(2 * time.Minute)) // a random latency (in nanoseconds) that can be up to 2 minutes } func TestNew(t *testing.T) { @@ -423,11 +419,11 @@ func TestNewExporter(t *testing.T) { var latency time.Duration if index == 0 { // first bucket value - latency = getRandomLatencyN(int64(fvalue * SecondToNanoseconds)) + latency = getRandomLatencyN(int64(fvalue * float64(time.Second))) } else { pvalue := dBuckets[index-1] // previous bucket value - latency = time.Duration(pvalue*SecondToNanoseconds) + - getRandomLatencyN(int64(dBuckets[0]*SecondToNanoseconds)) + latency = time.Duration(pvalue*float64(time.Second)) + + getRandomLatencyN(int64(dBuckets[0]*float64(time.Second))) } latencySum += latency.Seconds() monitoring.ObserveHTTPMethodLatency(serverController.Metrics, "GET", latency) diff --git a/pkg/extensions/config/config.go b/pkg/extensions/config/config.go index 47700b80..bc91891d 100644 --- a/pkg/extensions/config/config.go +++ b/pkg/extensions/config/config.go @@ -15,7 +15,7 @@ type ExtensionConfig struct { type SearchConfig struct { // CVE search CVE *CVEConfig - Enable bool + Enable *bool } type CVEConfig struct { @@ -23,7 +23,7 @@ type CVEConfig struct { } type MetricsConfig struct { - Enable bool + Enable *bool Prometheus *PrometheusConfig } diff --git a/pkg/extensions/extensions.go b/pkg/extensions/extensions.go index 599d85e3..1c61ea7c 100644 --- a/pkg/extensions/extensions.go +++ b/pkg/extensions/extensions.go @@ -35,13 +35,13 @@ func downloadTrivyDB(dbDir string, log log.Logger, updateInterval time.Duration) } func EnableExtensions(config *config.Config, log log.Logger, rootDir string) { - if config.Extensions.Search != nil && config.Extensions.Search.Enable && config.Extensions.Search.CVE != nil { + if config.Extensions.Search != nil && *config.Extensions.Search.Enable && config.Extensions.Search.CVE != nil { defaultUpdateInterval, _ := time.ParseDuration("2h") if config.Extensions.Search.CVE.UpdateInterval < defaultUpdateInterval { config.Extensions.Search.CVE.UpdateInterval = defaultUpdateInterval - log.Warn().Msg("CVE update interval set to too-short interval <= 1, changing update duration to 2 hours and continuing.") // nolint: lll + log.Warn().Msg("CVE update interval set to too-short interval < 2h, changing update duration to 2 hours and continuing.") // nolint: lll } go func() { @@ -56,7 +56,7 @@ func EnableExtensions(config *config.Config, log log.Logger, rootDir string) { } if config.Extensions.Metrics != nil && - config.Extensions.Metrics.Enable && + *config.Extensions.Metrics.Enable && config.Extensions.Metrics.Prometheus != nil { if config.Extensions.Metrics.Prometheus.Path == "" { config.Extensions.Metrics.Prometheus.Path = "/metrics" @@ -71,7 +71,7 @@ func EnableExtensions(config *config.Config, log log.Logger, rootDir string) { // EnableSyncExtension enables sync extension. func EnableSyncExtension(config *config.Config, wg *goSync.WaitGroup, storeController storage.StoreController, log log.Logger) { - if config.Extensions.Sync != nil { + if config.Extensions.Sync != nil && *config.Extensions.Sync.Enable { if err := sync.Run(*config.Extensions.Sync, storeController, wg, log); err != nil { log.Error().Err(err).Msg("Error encountered while setting up syncing") } @@ -87,7 +87,7 @@ func SetupRoutes(config *config.Config, router *mux.Router, storeController stor log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()} log.Info().Msg("setting up extensions routes") - if config.Extensions.Search != nil && config.Extensions.Search.Enable { + if config.Extensions.Search != nil && *config.Extensions.Search.Enable { var resConfig search.Config if config.Extensions.Search.CVE != nil { @@ -100,7 +100,7 @@ func SetupRoutes(config *config.Config, router *mux.Router, storeController stor Handler(gqlHandler.NewDefaultServer(search.NewExecutableSchema(resConfig))) } - if config.Extensions.Metrics != nil && config.Extensions.Metrics.Enable { + if config.Extensions.Metrics != nil && *config.Extensions.Metrics.Enable { router.PathPrefix(config.Extensions.Metrics.Prometheus.Path). Handler(promhttp.Handler()) } diff --git a/pkg/extensions/monitoring/monitoring_test.go b/pkg/extensions/monitoring/monitoring_test.go index e609e4e4..1143e7de 100644 --- a/pkg/extensions/monitoring/monitoring_test.go +++ b/pkg/extensions/monitoring/monitoring_test.go @@ -36,8 +36,9 @@ func TestExtensionMetrics(t *testing.T) { conf.Storage.RootDirectory = rootDir conf.Extensions = &extconf.ExtensionConfig{} + enabled := true conf.Extensions.Metrics = &extconf.MetricsConfig{ - Enable: true, + Enable: &enabled, Prometheus: &extconf.PrometheusConfig{Path: "/metrics"}, } @@ -95,7 +96,8 @@ func TestExtensionMetrics(t *testing.T) { conf.Storage.RootDirectory = rootDir conf.Extensions = &extconf.ExtensionConfig{} - conf.Extensions.Metrics = &extconf.MetricsConfig{Enable: false} + var disabled bool + conf.Extensions.Metrics = &extconf.MetricsConfig{Enable: &disabled} ctlr := api.NewController(conf) So(ctlr, ShouldNotBeNil) diff --git a/pkg/extensions/search/common/common_test.go b/pkg/extensions/search/common/common_test.go index 6d32e996..ccbfe778 100644 --- a/pkg/extensions/search/common/common_test.go +++ b/pkg/extensions/search/common/common_test.go @@ -186,8 +186,9 @@ func TestLatestTagSearchHTTP(t *testing.T) { conf.Storage.RootDirectory = rootDir conf.Storage.SubPaths = make(map[string]config.StorageConfig) conf.Storage.SubPaths["/a"] = config.StorageConfig{RootDirectory: subRootDir} + defaultVal := true conf.Extensions = &extconf.ExtensionConfig{ - Search: &extconf.SearchConfig{Enable: true}, + Search: &extconf.SearchConfig{Enable: &defaultVal}, } conf.Extensions.Search.CVE = nil diff --git a/pkg/extensions/search/cve/cve_test.go b/pkg/extensions/search/cve/cve_test.go index 3edf7607..9e038e0e 100644 --- a/pkg/extensions/search/cve/cve_test.go +++ b/pkg/extensions/search/cve/cve_test.go @@ -380,7 +380,7 @@ func TestDownloadDB(t *testing.T) { } func TestCVESearch(t *testing.T) { - Convey("Test image vulenrability scanning", t, func() { + Convey("Test image vulnerability scanning", t, func() { updateDuration, _ = time.ParseDuration("1h") port := GetFreePort() baseURL := GetBaseURL(port) @@ -395,18 +395,21 @@ func TestCVESearch(t *testing.T) { }, } - ctlr := api.NewController(conf) - ctlr.Config.Storage.RootDirectory = dbDir + conf.Storage.RootDirectory = dbDir cveConfig := &extconf.CVEConfig{ UpdateInterval: updateDuration, } + defaultVal := true searchConfig := &extconf.SearchConfig{ + Enable: &defaultVal, CVE: cveConfig, - Enable: true, } - ctlr.Config.Extensions = &extconf.ExtensionConfig{ + conf.Extensions = &extconf.ExtensionConfig{ Search: searchConfig, } + + ctlr := api.NewController(conf) + go func() { // this blocks if err := ctlr.Run(); err != nil { diff --git a/pkg/extensions/search/digest/digest_test.go b/pkg/extensions/search/digest/digest_test.go index 402d2477..7bfbb169 100644 --- a/pkg/extensions/search/digest/digest_test.go +++ b/pkg/extensions/search/digest/digest_test.go @@ -145,8 +145,9 @@ func TestDigestSearchHTTP(t *testing.T) { conf := config.New() conf.HTTP.Port = port conf.Storage.RootDirectory = rootDir + defaultVal := true conf.Extensions = &extconf.ExtensionConfig{ - Search: &extconf.SearchConfig{Enable: true}, + Search: &extconf.SearchConfig{Enable: &defaultVal}, } ctlr := api.NewController(conf) @@ -272,8 +273,9 @@ func TestDigestSearchHTTPSubPaths(t *testing.T) { baseURL := GetBaseURL(port) conf := config.New() conf.HTTP.Port = port + defaultVal := true conf.Extensions = &extconf.ExtensionConfig{ - Search: &extconf.SearchConfig{Enable: true}, + Search: &extconf.SearchConfig{Enable: &defaultVal}, } ctlr := api.NewController(conf) @@ -339,6 +341,7 @@ func TestDigestSearchHTTPSubPaths(t *testing.T) { func TestDigestSearchDisabled(t *testing.T) { Convey("Test disabling image search", t, func() { + var disabled bool dir, err := ioutil.TempDir("", "digest_test") So(err, ShouldBeNil) port := GetFreePort() @@ -347,7 +350,7 @@ func TestDigestSearchDisabled(t *testing.T) { conf.HTTP.Port = port conf.Storage.RootDirectory = dir conf.Extensions = &extconf.ExtensionConfig{ - Search: &extconf.SearchConfig{Enable: false}, + Search: &extconf.SearchConfig{Enable: &disabled}, } ctlr := api.NewController(conf) diff --git a/pkg/extensions/sync/sync.go b/pkg/extensions/sync/sync.go index 6f2e8025..891cfb03 100644 --- a/pkg/extensions/sync/sync.go +++ b/pkg/extensions/sync/sync.go @@ -42,6 +42,7 @@ type Credentials struct { } type Config struct { + Enable *bool CredentialsFile string Registries []RegistryConfig } diff --git a/pkg/extensions/sync/sync_test.go b/pkg/extensions/sync/sync_test.go index 7b17e2a1..267afcbc 100644 --- a/pkg/extensions/sync/sync_test.go +++ b/pkg/extensions/sync/sync_test.go @@ -119,7 +119,7 @@ func startUpstreamServer(secure, basicAuth bool) (*api.Controller, string, strin client.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) - cert, err := tls.LoadX509KeyPair("../../../test/data/client.cert", "../../../test/data/client.key") + cert, err := tls.LoadX509KeyPair(ClientCert, ClientKey) if err != nil { panic(err) } @@ -202,7 +202,7 @@ func startDownstreamServer(secure bool, syncConfig *sync.Config) (*api.Controlle client.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) - cert, err := tls.LoadX509KeyPair("../../../test/data/client.cert", "../../../test/data/client.key") + cert, err := tls.LoadX509KeyPair(ClientCert, ClientKey) if err != nil { panic(err) } @@ -279,7 +279,9 @@ func TestOnDemand(t *testing.T) { OnDemand: true, } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -413,7 +415,11 @@ func TestPeriodically(t *testing.T) { RetryDelay: &delay, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -485,7 +491,10 @@ func TestPeriodically(t *testing.T) { CertDir: "", } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -578,7 +587,11 @@ func TestPermsDenied(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -634,7 +647,11 @@ func TestBadTLS(t *testing.T) { TLSVerify: &tlsVerify, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(true, syncConfig) defer os.RemoveAll(destDir) @@ -729,7 +746,11 @@ func TestTLS(t *testing.T) { CertDir: destClientCertDir, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, _, destDir, _ := startDownstreamServer(true, syncConfig) defer os.RemoveAll(destDir) @@ -791,7 +812,9 @@ func TestBasicAuth(t *testing.T) { CertDir: "", } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, CredentialsFile: credentialsFile, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -896,8 +919,9 @@ func TestBasicAuth(t *testing.T) { } destConfig.Extensions = &extconf.ExtensionConfig{} - destConfig.Extensions.Search = nil + defaultVal := true destConfig.Extensions.Sync = &sync.Config{ + Enable: &defaultVal, CredentialsFile: credentialsFile, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -973,7 +997,9 @@ func TestBasicAuth(t *testing.T) { CertDir: "", } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, CredentialsFile: credentialsFile, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -1019,8 +1045,10 @@ func TestBasicAuth(t *testing.T) { OnDemand: false, } + defaultVal := true // add file path to the credentials syncConfig := &sync.Config{ + Enable: &defaultVal, CredentialsFile: credentialsFile, Registries: []sync.RegistryConfig{ unreacheableSyncRegistryConfig1, @@ -1115,7 +1143,11 @@ func TestBadURL(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1159,7 +1191,11 @@ func TestNoImagesByRegex(t *testing.T) { CertDir: "", } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1217,7 +1253,11 @@ func TestInvalidRegex(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, _, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1272,7 +1312,11 @@ func TestNotSemver(t *testing.T) { CertDir: "", } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1367,7 +1411,11 @@ func TestInvalidCerts(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1421,7 +1469,11 @@ func TestInvalidUrl(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1469,7 +1521,9 @@ func TestInvalidTags(t *testing.T) { OnDemand: true, } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -1555,7 +1609,9 @@ func TestSubPaths(t *testing.T) { OnDemand: true, } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -1662,7 +1718,11 @@ func TestOnDemandRepoErr(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1708,7 +1768,11 @@ func TestOnDemandContentFiltering(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1744,7 +1808,11 @@ func TestOnDemandContentFiltering(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1790,7 +1858,11 @@ func TestConfigRules(t *testing.T) { OnDemand: false, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1817,7 +1889,11 @@ func TestConfigRules(t *testing.T) { OnDemand: false, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1841,7 +1917,11 @@ func TestConfigRules(t *testing.T) { OnDemand: false, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1888,7 +1968,11 @@ func TestMultipleURLs(t *testing.T) { CertDir: "", } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dc, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -1983,7 +2067,9 @@ func TestPeriodicallySignatures(t *testing.T) { OnDemand: true, } + defaultVal := true syncConfig := &sync.Config{ + Enable: &defaultVal, Registries: []sync.RegistryConfig{syncRegistryConfig}, } @@ -2258,7 +2344,11 @@ func TestOnDemandRetryGoroutine(t *testing.T) { syncRegistryConfig.MaxRetries = &maxRetries syncRegistryConfig.RetryDelay = &delay - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dc, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -2336,7 +2426,11 @@ func TestOnDemandMultipleRetries(t *testing.T) { syncRegistryConfig.MaxRetries = &maxRetries syncRegistryConfig.RetryDelay = &delay - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dc, destBaseURL, destDir, destClient := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -2446,7 +2540,11 @@ func TestOnDemandPullsOnce(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dc, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -2542,7 +2640,11 @@ func TestError(t *testing.T) { CertDir: "", } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, client := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -2601,7 +2703,11 @@ func TestSignaturesOnDemand(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir) @@ -2737,7 +2843,11 @@ func TestOnlySignaturesOnDemand(t *testing.T) { OnDemand: true, } - syncConfig := &sync.Config{Registries: []sync.RegistryConfig{syncBadRegistryConfig, syncRegistryConfig}} + defaultVal := true + syncConfig := &sync.Config{ + Enable: &defaultVal, + Registries: []sync.RegistryConfig{syncBadRegistryConfig, syncRegistryConfig}, + } dctlr, destBaseURL, destDir, _ := startDownstreamServer(false, syncConfig) defer os.RemoveAll(destDir)