mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
fix: don't show corrupted trivy-db warning for first run (#8991)
This commit is contained in:
@@ -110,11 +110,12 @@ 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:
|
||||
// There are 3 cases when DownloadAt field is zero:
|
||||
// - metadata file was not created yet. This is the first run of Trivy.
|
||||
// - 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 {
|
||||
if !noRequiredFiles && 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
|
||||
}
|
||||
@@ -131,10 +132,11 @@ func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool)
|
||||
}
|
||||
|
||||
if skip {
|
||||
log.DebugContext(ctx, "Skipping DB update...")
|
||||
if err = c.validate(meta); err != nil {
|
||||
return false, xerrors.Errorf("validate error: %w", err)
|
||||
}
|
||||
|
||||
log.DebugContext(ctx, "Skipping DB update...")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package db_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -13,6 +16,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/clock"
|
||||
"github.com/aquasecurity/trivy/pkg/db"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestClient_NeedsUpdate(t *testing.T) {
|
||||
@@ -27,14 +31,16 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
dbFileExists bool
|
||||
metadata metadata.Metadata
|
||||
want bool
|
||||
wantLogs []string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
Version: db.SchemaVersion,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
@@ -43,20 +49,31 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{},
|
||||
want: true,
|
||||
wantLogs: []string{
|
||||
"There is no valid metadata file",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path for first run without trivy.db",
|
||||
dbFileExists: false,
|
||||
want: true,
|
||||
wantLogs: []string{
|
||||
"There is no db file",
|
||||
"There is no valid metadata file",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path with old schema version",
|
||||
dbFileExists: true,
|
||||
metadata: metadata.Metadata{
|
||||
Version: 0,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
Version: 0,
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
want: true,
|
||||
wantLogs: []string{
|
||||
"The local DB schema version does not match with supported version schema.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path with --skip-db-update",
|
||||
@@ -68,6 +85,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
},
|
||||
skip: true,
|
||||
want: false,
|
||||
wantLogs: []string{
|
||||
"Skipping DB update...",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skip downloading DB",
|
||||
@@ -78,6 +98,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
DownloadedAt: timeDownloadAt,
|
||||
},
|
||||
want: false,
|
||||
wantLogs: []string{
|
||||
"DB update was skipped because the local DB is the latest",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "newer schema version",
|
||||
@@ -89,12 +112,20 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
},
|
||||
wantErr: fmt.Sprintf("the version of DB schema doesn't match. Local DB: %d, Expected: %d",
|
||||
db.SchemaVersion+1, db.SchemaVersion),
|
||||
wantLogs: []string{
|
||||
"Trivy version is old. Update to the latest version.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--skip-db-update without trivy.db on the first run",
|
||||
dbFileExists: false,
|
||||
skip: true,
|
||||
wantErr: "--skip-db-update cannot be specified on the first run",
|
||||
wantLogs: []string{
|
||||
"There is no db file",
|
||||
"There is no valid metadata file",
|
||||
"The first run cannot skip downloading DB",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--skip-db-update without metadata.json on the first run",
|
||||
@@ -102,6 +133,10 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
metadata: metadata.Metadata{},
|
||||
skip: true,
|
||||
wantErr: "--skip-db-update cannot be specified on the first run",
|
||||
wantLogs: []string{
|
||||
"There is no valid metadata file",
|
||||
"The first run cannot skip downloading DB",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--skip-db-update with different schema version",
|
||||
@@ -114,6 +149,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
skip: true,
|
||||
wantErr: fmt.Sprintf("--skip-db-update cannot be specified with the old DB schema. Local DB: %d, Expected: %d",
|
||||
0, db.SchemaVersion),
|
||||
wantLogs: []string{
|
||||
"The local DB has an old schema version which is not supported by the current version of Trivy CLI. DB needs to be updated.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy with old DownloadedAt",
|
||||
@@ -134,6 +172,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
DownloadedAt: time.Date(2019, 9, 30, 23, 30, 0, 0, time.UTC),
|
||||
},
|
||||
want: false,
|
||||
wantLogs: []string{
|
||||
"DB update was skipped because the local DB was downloaded during the last hour",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is false",
|
||||
@@ -145,6 +186,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
},
|
||||
want: true,
|
||||
wantLogs: []string{
|
||||
"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.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is true",
|
||||
@@ -156,6 +200,9 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
NextUpdate: timeNextUpdateDay1,
|
||||
},
|
||||
want: false,
|
||||
wantLogs: []string{
|
||||
"Skipping DB update...",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DownloadedAt is zero, skip is true, old schema version",
|
||||
@@ -168,11 +215,18 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
},
|
||||
wantErr: "--skip-db-update cannot be specified with the old DB schema. Local DB: 0, Expected: 2",
|
||||
want: false,
|
||||
wantLogs: []string{
|
||||
"The local DB has an old schema version which is not supported by the current version of Trivy CLI. DB needs to be updated.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
out := bytes.NewBuffer(nil)
|
||||
logger := log.New(log.NewHandler(out, &log.Options{Level: log.LevelDebug}))
|
||||
log.SetDefault(logger)
|
||||
|
||||
dbDir := db.Dir(t.TempDir())
|
||||
if tt.metadata != (metadata.Metadata{}) {
|
||||
meta := metadata.NewClient(dbDir)
|
||||
@@ -194,6 +248,12 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
client := db.NewClient(dbDir, true)
|
||||
needsUpdate, err := client.NeedsUpdate(ctx, "test", tt.skip)
|
||||
|
||||
// Compare log messages
|
||||
require.Len(t, lo.Compact(strings.Split(out.String(), "\n")), len(tt.wantLogs))
|
||||
for _, logMsg := range tt.wantLogs {
|
||||
assert.Contains(t, out.String(), logMsg)
|
||||
}
|
||||
|
||||
switch {
|
||||
case tt.wantErr != "":
|
||||
require.ErrorContains(t, err, tt.wantErr, tt.name)
|
||||
|
||||
Reference in New Issue
Block a user