refactor: replace global cache directory with parameter passing (#6986)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-06-21 13:45:39 +04:00
committed by GitHub
parent 7eabb92ec2
commit 648ead9553
12 changed files with 86 additions and 58 deletions

33
pkg/cache/client.go vendored
View File

@@ -21,6 +21,7 @@ const (
)
type Client struct {
dir string
Cache
}
@@ -115,7 +116,8 @@ func NewType(backend string) (Type, error) {
}
// NewClient returns a new cache client
func NewClient(opts Options) (*Client, error) {
func NewClient(dir string, opts Options) (*Client, error) {
client := &Client{dir: dir}
if opts.Type == TypeRedis {
log.Info("Redis cache", log.String("url", opts.Redis.BackendMasked()))
options, err := redis.ParseURL(opts.Redis.Backend)
@@ -140,34 +142,27 @@ func NewClient(opts Options) (*Client, error) {
}
}
redisCache := NewRedisCache(options, opts.TTL)
return &Client{Cache: redisCache}, nil
client.Cache = NewRedisCache(options, opts.TTL)
return client, nil
}
// standalone mode
fsCache, err := NewFSCache(Dir())
var err error
client.Cache, err = NewFSCache(dir)
if err != nil {
return nil, xerrors.Errorf("unable to initialize fs cache: %w", err)
}
return &Client{Cache: fsCache}, nil
return client, nil
}
// Reset resets the cache
func (c *Client) Reset() (err error) {
if err := c.ClearDB(); err != nil {
return xerrors.Errorf("failed to clear the database: %w", err)
func (c *Client) Reset() error {
log.Info("Removing all caches...")
if err := c.Clear(); err != nil {
return xerrors.Errorf("failed to remove the cache: %w", err)
}
if err := c.ClearArtifacts(); err != nil {
return xerrors.Errorf("failed to clear the artifact cache: %w", err)
}
return nil
}
// ClearDB clears the DB cache
func (c *Client) ClearDB() (err error) {
log.Info("Removing DB file...")
if err = os.RemoveAll(Dir()); err != nil {
return xerrors.Errorf("failed to remove the directory (%s) : %w", Dir(), err)
if err := os.RemoveAll(c.dir); err != nil {
return xerrors.Errorf("failed to remove the directory (%s) : %w", c.dir, err)
}
return nil
}

View File

@@ -1,6 +1,8 @@
package cache_test
import (
"os"
"path/filepath"
"testing"
"time"
@@ -127,3 +129,51 @@ func TestRedisOptions_BackendMasked(t *testing.T) {
})
}
}
func TestClient_Reset(t *testing.T) {
// Create a temporary directory for testing
tempDir := t.TempDir()
// Create test files and subdirectories
subDir := filepath.Join(tempDir, "subdir")
err := os.MkdirAll(subDir, 0755)
require.NoError(t, err)
testFile := filepath.Join(tempDir, "testfile.txt")
err = os.WriteFile(testFile, []byte("test content"), 0644)
require.NoError(t, err)
// Create a cache client
client, err := cache.NewClient(tempDir, cache.Options{Type: cache.TypeFS})
require.NoError(t, err)
// Call Reset method
err = client.Reset()
require.NoError(t, err)
// Verify that the subdirectory no longer exists
require.NoDirExists(t, subDir, "Subdirectory should not exist after Reset")
// Verify that the test file no longer exists
require.NoFileExists(t, testFile, "Test file should not exist after Reset")
// Verify that the cache directory no longer exists
require.NoDirExists(t, tempDir, "Cache directory should not exist after Reset")
}
func TestClient_ClearArtifacts(t *testing.T) {
// Create a temporary directory for testing
tempDir := t.TempDir()
// Create a client
client, err := cache.NewClient(tempDir, cache.Options{Type: cache.TypeFS})
require.NoError(t, err)
require.FileExists(t, filepath.Join(tempDir, "fanal", "fanal.db"), "Database file should exist")
// Call ClearArtifacts method
err = client.ClearArtifacts()
require.NoError(t, err)
require.NoDirExists(t, filepath.Join(tempDir, "fanal"), "Artifact cache should not exist after ClearArtifacts")
}

19
pkg/cache/dir.go vendored
View File

@@ -5,26 +5,11 @@ import (
"path/filepath"
)
var cacheDir string
// defaultDir returns/creates the cache-dir to be used for trivy operations
func defaultDir() string {
// DefaultDir returns/creates the cache-dir to be used for trivy operations
func DefaultDir() string {
tmpDir, err := os.UserCacheDir()
if err != nil {
tmpDir = os.TempDir()
}
return filepath.Join(tmpDir, "trivy")
}
// Dir returns the directory used for caching
func Dir() string {
if cacheDir == "" {
return defaultDir()
}
return cacheDir
}
// SetDir sets the trivy cache dir
func SetDir(dir string) {
cacheDir = dir
}

View File

@@ -110,10 +110,9 @@ func NewApp() *cobra.Command {
func loadPluginCommands() []*cobra.Command {
ctx := context.Background()
manager := plugin.NewManager()
var commands []*cobra.Command
plugins, err := manager.LoadAll(ctx)
plugins, err := plugin.NewManager().LoadAll(ctx)
if err != nil {
log.DebugContext(ctx, "No plugins loaded")
return nil

View File

@@ -350,12 +350,11 @@ func (r *runner) initCache(opts flag.Options) error {
}
// standalone mode
cache.SetDir(opts.CacheDir)
cacheClient, err := cache.NewClient(opts.CacheOptions.CacheBackendOptions)
cacheClient, err := cache.NewClient(opts.CacheDir, opts.CacheOptions.CacheBackendOptions)
if err != nil {
return xerrors.Errorf("unable to initialize the cache: %w", err)
}
log.Debug("Cache dir", log.String("dir", cache.Dir()))
log.Debug("Cache dir", log.String("dir", opts.CacheDir))
if opts.Reset {
defer cacheClient.Close()
@@ -366,7 +365,7 @@ func (r *runner) initCache(opts flag.Options) error {
}
if opts.ResetChecksBundle {
c, err := policy.NewClient(cache.Dir(), true, opts.MisconfOptions.ChecksBundleRepository)
c, err := policy.NewClient(opts.CacheDir, true, opts.MisconfOptions.ChecksBundleRepository)
if err != nil {
return xerrors.Errorf("failed to instantiate check client: %w", err)
}

View File

@@ -19,16 +19,15 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
log.InitLogger(opts.Debug, opts.Quiet)
// configure cache dir
cache.SetDir(opts.CacheDir)
cacheClient, err := cache.NewClient(opts.CacheOptions.CacheBackendOptions)
cacheClient, err := cache.NewClient(opts.CacheDir, opts.CacheOptions.CacheBackendOptions)
if err != nil {
return xerrors.Errorf("server cache error: %w", err)
}
defer cacheClient.Close()
log.Debug("Cache", log.String("dir", cache.Dir()))
log.Debug("Cache", log.String("dir", opts.CacheDir))
if opts.Reset {
return cacheClient.ClearDB()
return cacheClient.Reset()
}
// download the database file

View File

@@ -55,7 +55,7 @@ var (
CacheDirFlag = Flag[string]{
Name: "cache-dir",
ConfigName: "cache.dir",
Default: cache.Dir(),
Default: cache.DefaultDir(),
Usage: "cache directory",
Persistent: true,
}

View File

@@ -14,7 +14,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/cache"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/oci"
)
@@ -97,7 +96,6 @@ func TestArtifact_Download(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tempDir := t.TempDir()
cache.SetDir(tempDir)
// Mock image
img := new(fakei.FakeImage)

View File

@@ -12,13 +12,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/plugin"
)
func TestManager_Update(t *testing.T) {
tempDir := t.TempDir()
cache.SetDir(tempDir)
t.Setenv("XDG_DATA_HOME", tempDir)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte(`this is index`))
@@ -30,7 +29,7 @@ func TestManager_Update(t *testing.T) {
err := manager.Update(context.Background())
require.NoError(t, err)
indexPath := filepath.Join(tempDir, "plugin", "index.yaml")
indexPath := filepath.Join(tempDir, ".trivy", "plugins", "index.yaml")
assert.FileExists(t, indexPath)
b, err := os.ReadFile(indexPath)
@@ -73,7 +72,7 @@ bar A bar plugin
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cache.SetDir(tt.dir)
t.Setenv("XDG_DATA_HOME", tt.dir)
var got bytes.Buffer
m := plugin.NewManager(plugin.WithWriter(&got))

View File

@@ -14,7 +14,6 @@ import (
"gopkg.in/yaml.v3"
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/downloader"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
@@ -59,12 +58,13 @@ type Manager struct {
}
func NewManager(opts ...ManagerOption) *Manager {
root := filepath.Join(fsutils.HomeDir(), pluginsRelativeDir)
m := &Manager{
w: os.Stdout,
indexURL: indexURL,
logger: log.WithPrefix("plugin"),
pluginRoot: filepath.Join(fsutils.HomeDir(), pluginsRelativeDir),
indexPath: filepath.Join(cache.Dir(), "plugin", "index.yaml"),
pluginRoot: root,
indexPath: filepath.Join(root, "index.yaml"),
}
for _, opt := range opts {
opt(m)

View File

@@ -20,11 +20,11 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/internal/gittest"
"github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/clock"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/plugin"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
func setupGitRepository(t *testing.T, repo, dir string) *httptest.Server {
@@ -200,7 +200,11 @@ func TestManager_Install(t *testing.T) {
t.Setenv("XDG_DATA_HOME", dst)
// For plugin index
cache.SetDir("testdata")
pluginDir := filepath.Join(dst, ".trivy", "plugins")
err := os.MkdirAll(pluginDir, 0755)
require.NoError(t, err)
_, err = fsutils.CopyFile("testdata/.trivy/plugins/index.yaml", filepath.Join(pluginDir, "index.yaml"))
require.NoError(t, err)
if tt.installed != nil {
setupInstalledPlugin(t, dst, *tt.installed)