mirror of
https://github.com/aquasecurity/trivy.git
synced 2026-01-31 13:53:14 +08:00
refactor(db): change logic to detect wrong DB (#8864)
This commit is contained in:
@@ -60,9 +60,10 @@ func initDB(t *testing.T) string {
|
||||
defer dbtest.Close()
|
||||
|
||||
err = metadata.NewClient(db.Dir(cacheDir)).Update(metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: time.Now().Add(24 * time.Hour),
|
||||
UpdatedAt: time.Now(),
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: time.Now().Add(24 * time.Hour),
|
||||
UpdatedAt: time.Now(),
|
||||
DownloadedAt: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
18
pkg/db/db.go
18
pkg/db/db.go
@@ -110,9 +110,18 @@ func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool)
|
||||
meta = metadata.Metadata{Version: db.SchemaVersion}
|
||||
}
|
||||
|
||||
// There are 2 cases when DownloadAt field is zero:
|
||||
// - trivy-db was downloaded with `oras`. In this case user can use `--skip-db-update` (like for air-gapped) or re-download trivy-db.
|
||||
// - trivy-db was corrupted while copying from tmp directory to cache directory. We should update this trivy-db.
|
||||
// We can't detect these cases, so we will show warning for users who use oras + air-gapped.
|
||||
if meta.DownloadedAt.IsZero() && !skip {
|
||||
log.WarnContext(ctx, "Trivy DB may be corrupted and will be re-downloaded. If you manually downloaded DB - use the `--skip-db-update` flag to skip updating DB.")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if skip && noRequiredFiles {
|
||||
log.ErrorContext(ctx, "The first run cannot skip downloading DB")
|
||||
return false, xerrors.New("--skip-update cannot be specified on the first run")
|
||||
return false, xerrors.New("--skip-db-update cannot be specified on the first run")
|
||||
}
|
||||
|
||||
if db.SchemaVersion < meta.Version {
|
||||
@@ -141,7 +150,7 @@ func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool)
|
||||
func (c *Client) validate(meta metadata.Metadata) error {
|
||||
if db.SchemaVersion != meta.Version {
|
||||
log.Error("The local DB has an old schema version which is not supported by the current version of Trivy CLI. DB needs to be updated.")
|
||||
return xerrors.Errorf("--skip-update cannot be specified with the old DB schema. Local DB: %d, Expected: %d",
|
||||
return xerrors.Errorf("--skip-db-update cannot be specified with the old DB schema. Local DB: %d, Expected: %d",
|
||||
meta.Version, db.SchemaVersion)
|
||||
}
|
||||
return nil
|
||||
@@ -163,11 +172,6 @@ func (c *Client) isNewDB(ctx context.Context, meta metadata.Metadata) bool {
|
||||
|
||||
// Download downloads the DB file
|
||||
func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOptions) error {
|
||||
// Remove the metadata file under the cache directory before downloading DB
|
||||
if err := c.metadata.Delete(); err != nil {
|
||||
log.DebugContext(ctx, "No metadata file")
|
||||
}
|
||||
|
||||
if err := c.downloadDB(ctx, opt, dst); err != nil {
|
||||
return xerrors.Errorf("OCI artifact error: %w", err)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
timeNextUpdateDay1 := time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC)
|
||||
timeNextUpdateDay2 := time.Date(2019, 10, 2, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
timeDownloadAt := time.Date(2019, 9, 30, 22, 30, 0, 0, time.UTC)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
skip bool
|
||||
@@ -57,11 +59,12 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "happy path with --skip-update",
|
||||
name: "happy path with --skip-db-update",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
skip: true,
|
||||
want: false,
|
||||
@@ -70,8 +73,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
name: "skip downloading DB",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay2,
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay2,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
@@ -79,34 +83,36 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
name: "newer schema version",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion + 1,
|
||||
NextUpdate: timeNextUpdateDay2,
|
||||
Version: db.SchemaVersion + 1,
|
||||
NextUpdate: timeNextUpdateDay2,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
wantErr: fmt.Sprintf("the version of DB schema doesn't match. Local DB: %d, Expected: %d",
|
||||
db.SchemaVersion+1, db.SchemaVersion),
|
||||
},
|
||||
{
|
||||
name: "--skip-update without trivy.db on the first run",
|
||||
name: "--skip-db-update without trivy.db on the first run",
|
||||
dbFileExists: false,
|
||||
skip: true,
|
||||
wantErr: "--skip-update cannot be specified on the first run",
|
||||
wantErr: "--skip-db-update cannot be specified on the first run",
|
||||
},
|
||||
{
|
||||
name: "--skip-update without metadata.json on the first run",
|
||||
name: "--skip-db-update without metadata.json on the first run",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{},
|
||||
skip: true,
|
||||
wantErr: "--skip-update cannot be specified on the first run",
|
||||
wantErr: "--skip-db-update cannot be specified on the first run",
|
||||
},
|
||||
{
|
||||
name: "--skip-update with different schema version",
|
||||
name: "--skip-db-update with different schema version",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: 0,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
Version: 0,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
skip: true,
|
||||
wantErr: fmt.Sprintf("--skip-update cannot be specified with the old DB schema. Local DB: %d, Expected: %d",
|
||||
wantErr: fmt.Sprintf("--skip-db-update cannot be specified with the old DB schema. Local DB: %d, Expected: %d",
|
||||
0, db.SchemaVersion),
|
||||
},
|
||||
{
|
||||
@@ -115,7 +121,7 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
DownloadedAt: time.Date(2019, 9, 30, 22, 30, 0, 0, time.UTC),
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
@@ -129,6 +135,40 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is false",
|
||||
dbFileExists: true,
|
||||
skip: false,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
DownloadedAt: time.Time{}, // zero time
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is true",
|
||||
dbFileExists: true,
|
||||
skip: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
DownloadedAt: time.Time{}, // zero time
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is true, old schema version",
|
||||
dbFileExists: true,
|
||||
skip: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: 0,
|
||||
DownloadedAt: time.Time{}, // zero time
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
},
|
||||
wantErr: "--skip-db-update cannot be specified with the old DB schema. Local DB: 0, Expected: 2",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user