mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
refactor: replace global cache directory with parameter passing (#6986)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
33
pkg/cache/client.go
vendored
33
pkg/cache/client.go
vendored
@@ -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
|
||||
}
|
||||
|
||||
50
pkg/cache/client_test.go
vendored
50
pkg/cache/client_test.go
vendored
@@ -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
19
pkg/cache/dir.go
vendored
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user